<!DOCTYPE html>
<html lang=zh>
<head>
    <meta charset="utf-8">
    
    <title>Java技术栈</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
    <meta name="description" content="分享Java后端技术干货，包括最新Java核心技术，高并发&amp;多线程编程，分布式&amp;微服务，架构设计，Java高级面试题，数据结构及算法，人工智能&amp;区块链应用，最新行业动态等。">
<meta name="keywords" content="Java技术, Spring Boot, Spring Cloud">
<meta property="og:type" content="website">
<meta property="og:title" content="Java技术栈">
<meta property="og:url" content="http://youanyyou.gitee.io/javastack/page/2/index.html">
<meta property="og:site_name" content="Java技术栈">
<meta property="og:description" content="分享Java后端技术干货，包括最新Java核心技术，高并发&amp;多线程编程，分布式&amp;微服务，架构设计，Java高级面试题，数据结构及算法，人工智能&amp;区块链应用，最新行业动态等。">
<meta property="og:locale" content="zh-CN">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Java技术栈">
<meta name="twitter:description" content="分享Java后端技术干货，包括最新Java核心技术，高并发&amp;多线程编程，分布式&amp;微服务，架构设计，Java高级面试题，数据结构及算法，人工智能&amp;区块链应用，最新行业动态等。">
    

    
        <link rel="alternate" href="/" title="Java技术栈" type="application/atom+xml" />
    

    

    <link rel="stylesheet" href="/javastack/libs/font-awesome/css/font-awesome.min.css">
    <link rel="stylesheet" href="/javastack/libs/open-sans/styles.css">
    <link rel="stylesheet" href="/javastack/libs/source-code-pro/styles.css">

    <link rel="stylesheet" href="/javastack/css/style.css">

    <script src="/javastack/libs/jquery/2.1.3/jquery.min.js"></script>
    
    
        <link rel="stylesheet" href="/javastack/libs/lightgallery/css/lightgallery.min.css">
    
    
        <link rel="stylesheet" href="/javastack/libs/justified-gallery/justifiedGallery.min.css">
    
    
    
    


</head>

<body>
    <div id="container">
        <header id="header">
    <div id="header-main" class="header-inner">
        <div class="outer">
            <a href="/javastack/" id="logo">
                <i class="logo"></i>
                <span class="site-title">Java技术栈</span>
            </a>
            <nav id="main-nav">
                
                    <a class="main-nav-link" href="/javastack/.">首页</a>
                
                    <a class="main-nav-link" href="/javastack/archives">归档</a>
                
                    <a class="main-nav-link" href="/javastack/categories">分类</a>
                
                    <a class="main-nav-link" href="/javastack/tags">标签</a>
                
                    <a class="main-nav-link" href="/javastack/about">关于</a>
                
            </nav>
            
                
                <nav id="sub-nav">
                    <div class="profile" id="profile-nav">
                        <a id="profile-anchor" href="javascript:;">
                            <img class="avatar" src="/javastack/css/images/avatar.jpg" />
                            <i class="fa fa-caret-down"></i>
                        </a>
                    </div>
                </nav>
            
            <div id="search-form-wrap">

    <form class="search-form">
        <input type="text" class="ins-search-input search-form-input" placeholder="搜索" />
        <button type="submit" class="search-form-submit"></button>
    </form>
    <div class="ins-search">
    <div class="ins-search-mask"></div>
    <div class="ins-search-container">
        <div class="ins-input-wrapper">
            <input type="text" class="ins-search-input" placeholder="想要查找什么..." />
            <span class="ins-close ins-selectable"><i class="fa fa-times-circle"></i></span>
        </div>
        <div class="ins-section-wrapper">
            <div class="ins-section-container"></div>
        </div>
    </div>
</div>
<script>
(function (window) {
    var INSIGHT_CONFIG = {
        TRANSLATION: {
            POSTS: '文章',
            PAGES: '页面',
            CATEGORIES: '分类',
            TAGS: '标签',
            UNTITLED: '(未命名)',
        },
        ROOT_URL: '/javastack/',
        CONTENT_URL: '/javastack/content.json',
    };
    window.INSIGHT_CONFIG = INSIGHT_CONFIG;
})(window);
</script>
<script src="/javastack/js/insight.js"></script>

</div>
        </div>
    </div>
    <div id="main-nav-mobile" class="header-sub header-inner">
        <table class="menu outer">
            <tr>
                
                    <td><a class="main-nav-link" href="/javastack/.">首页</a></td>
                
                    <td><a class="main-nav-link" href="/javastack/archives">归档</a></td>
                
                    <td><a class="main-nav-link" href="/javastack/categories">分类</a></td>
                
                    <td><a class="main-nav-link" href="/javastack/tags">标签</a></td>
                
                    <td><a class="main-nav-link" href="/javastack/about">关于</a></td>
                
                <td>
                    
    <div class="search-form">
        <input type="text" class="ins-search-input search-form-input" placeholder="搜索" />
    </div>

                </td>
            </tr>
        </table>
    </div>
</header>

        <div class="outer">
            
                

<aside id="profile">
    <div class="inner profile-inner">
        <div class="base-info profile-block">
            <img id="avatar" src="/javastack/css/images/avatar.jpg" />
            <h2 id="name">Java技术栈</h2><br/>
            <h3 id="title">微信公众号,每日更新！</h3>
            <!--
            <span id="location">
                <i class="fa fa-map-marker"></i>Shenzhen, China
            </span>
            -->
            <a id="follow" target="_blank" href="http://youanyyou.gitee.io/javastack/css/images/avatar.jpg">扫描关注微信公众号</a>
        </div>
        <div class="article-info profile-block">
            <div class="article-info-block">
                113
                <span>文章</span>
            </div>
            <div class="article-info-block">
                58
                <span>标签</span>
            </div>
        </div>
        
        <div class="profile-block social-links">
            <table>
                <tr>
                    
                    
                    <td>
                        <a href="http://github.com/ppoffice/hexo-theme-icarus" target="_blank" title="github" class=tooltip>
                            <i class="fa fa-github"></i>
                        </a>
                    </td>
                    
                    <td>
                        <a href="/javastack/" target="_blank" title="twitter" class=tooltip>
                            <i class="fa fa-twitter"></i>
                        </a>
                    </td>
                    
                    <td>
                        <a href="/javastack/" target="_blank" title="facebook" class=tooltip>
                            <i class="fa fa-facebook"></i>
                        </a>
                    </td>
                    
                    <td>
                        <a href="/javastack/" target="_blank" title="dribbble" class=tooltip>
                            <i class="fa fa-dribbble"></i>
                        </a>
                    </td>
                    
                    <td>
                        <a href="/javastack/" target="_blank" title="rss" class=tooltip>
                            <i class="fa fa-rss"></i>
                        </a>
                    </td>
                    
                </tr>
            </table>
        </div>
        
    </div>
</aside>

            
            <section id="main">
    <article id="post-Spring Boot/Spring Boot Starters启动器" class="article article-type-post" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <h2 id="Starters是什么？"><a href="#Starters是什么？" class="headerlink" title="Starters是什么？"></a>Starters是什么？</h2><p>Starters可以理解为启动器，它包含了一系列可以集成到应用里面的依赖包，你可以一站式集成Spring及其他技术，而不需要到处找示例代码和依赖包。如你想使用Spring JPA访问数据库，只要加入spring-boot-starter-data-jpa启动器依赖就能使用了。</p>
<p>Starters包含了许多项目中需要用到的依赖，它们能快速持续的运行，都是一系列得到支持的管理传递性依赖。</p>
<h2 id="Starters命名"><a href="#Starters命名" class="headerlink" title="Starters命名"></a>Starters命名</h2><p>Spring Boot官方的启动器都是以spring-boot-starter-<em>命名的，</em>代表了一个特定的应用类型。</p>
<p>第三方的启动器不能以spring-boot开头命名，它们都被Spring Boot官方保留。一般一个第三方的应该这样命名，像mybatis的mybatis-spring-boot-starter。</p>
<h2 id="Starters分类"><a href="#Starters分类" class="headerlink" title="Starters分类"></a>Starters分类</h2><h4 id="1-Spring-Boot应用类启动器"><a href="#1-Spring-Boot应用类启动器" class="headerlink" title="1. Spring Boot应用类启动器"></a>1. Spring Boot应用类启动器</h4><table>
<thead>
<tr>
<th>启动器名称</th>
<th>功能描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>spring-boot-starter</td>
<td>包含自动配置、日志、YAML的支持。</td>
</tr>
<tr>
<td>spring-boot-starter-web</td>
<td>使用Spring MVC构建web 工程，包含restful，默认使用Tomcat容器。</td>
</tr>
<tr>
<td>…</td>
<td>…</td>
</tr>
</tbody>
</table>
<h4 id="2-Spring-Boot生产启动器"><a href="#2-Spring-Boot生产启动器" class="headerlink" title="2. Spring Boot生产启动器"></a>2. Spring Boot生产启动器</h4><table>
<thead>
<tr>
<th>启动器名称</th>
<th>功能描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>spring-boot-starter-actuator</td>
<td>提供生产环境特性，能监控管理应用。</td>
</tr>
</tbody>
</table>
<h4 id="3-Spring-Boot技术类启动器"><a href="#3-Spring-Boot技术类启动器" class="headerlink" title="3. Spring Boot技术类启动器"></a>3. Spring Boot技术类启动器</h4><table>
<thead>
<tr>
<th>启动器名称</th>
<th>功能描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>spring-boot-starter-json</td>
<td>提供对JSON的读写支持。</td>
</tr>
<tr>
<td>spring-boot-starter-logging</td>
<td>默认的日志启动器，默认使用Logback。</td>
</tr>
<tr>
<td>…</td>
<td>…</td>
</tr>
</tbody>
</table>
<h4 id="4-其他第三方启动器"><a href="#4-其他第三方启动器" class="headerlink" title="4. 其他第三方启动器"></a>4. 其他第三方启动器</h4><p>更多可以参考下面链接。</p>
<p><a href="https://github.com/spring-projects/spring-boot/blob/master/spring-boot-starters/README.adoc" target="_blank" rel="noopener">https://github.com/spring-projects/spring-boot/blob/master/spring-boot-starters/README.adoc</a></p>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">



</div>

    <a data-url="http://youanyyou.gitee.io/javastack/2018/04/18/Spring Boot/Spring Boot Starters启动器/" data-id="cjg4zd8ng003ahg8aq9coyp2a" class="article-share-link"><i class="fa fa-share"></i>分享到</a>
<script>
    (function ($) {
        // Prevent duplicate binding
        if (typeof(__SHARE_BUTTON_BINDED__) === 'undefined' || !__SHARE_BUTTON_BINDED__) {
            __SHARE_BUTTON_BINDED__ = true;
        } else {
            return;
        }
        $('body').on('click', function() {
            $('.article-share-box.on').removeClass('on');
        }).on('click', '.article-share-link', function(e) {
            e.stopPropagation();

            var $this = $(this),
                url = $this.attr('data-url'),
                encodedUrl = encodeURIComponent(url),
                id = 'article-share-box-' + $this.attr('data-id'),
                offset = $this.offset(),
                box;

            if ($('#' + id).length) {
                box = $('#' + id);

                if (box.hasClass('on')){
                    box.removeClass('on');
                    return;
                }
            } else {
                var html = [
                    '<div id="' + id + '" class="article-share-box">',
                        '<input class="article-share-input" value="' + url + '">',
                        '<div class="article-share-links">',
                            '<a href="https://twitter.com/intent/tweet?url=' + encodedUrl + '" class="fa fa-twitter article-share-twitter" target="_blank" title="Twitter"></a>',
                            '<a href="https://www.facebook.com/sharer.php?u=' + encodedUrl + '" class="fa fa-facebook article-share-facebook" target="_blank" title="Facebook"></a>',
                            '<a href="http://pinterest.com/pin/create/button/?url=' + encodedUrl + '" class="fa fa-pinterest article-share-pinterest" target="_blank" title="Pinterest"></a>',
                            '<a href="https://plus.google.com/share?url=' + encodedUrl + '" class="fa fa-google article-share-google" target="_blank" title="Google+"></a>',
                        '</div>',
                    '</div>'
                ].join('');

              box = $(html);

              $('body').append(box);
            }

            $('.article-share-box.on').hide();

            box.css({
                top: offset.top + 25,
                left: offset.left
            }).addClass('on');

        }).on('click', '.article-share-box', function (e) {
            e.stopPropagation();
        }).on('click', '.article-share-box-input', function () {
            $(this).select();
        }).on('click', '.article-share-box-link', function (e) {
            e.preventDefault();
            e.stopPropagation();

            window.open(this.href, 'article-share-box-window-' + Date.now(), 'width=500,height=450');
        });
    })(jQuery);
</script>

            
    

        </footer>
    </div>
    
</article>



    <article id="post-Spring Boot/Spring Boot开启的2种方式" class="article article-type-post" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <h2 id="Spring-Boot依赖"><a href="#Spring-Boot依赖" class="headerlink" title="Spring Boot依赖"></a>Spring Boot依赖</h2><p>使用Spring Boot很简单，先添加基础依赖包，有以下两种方式</p>
<h4 id="1-继承spring-boot-starter-parent项目"><a href="#1-继承spring-boot-starter-parent项目" class="headerlink" title="1. 继承spring-boot-starter-parent项目"></a>1. 继承spring-boot-starter-parent项目</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;parent&gt;</span><br><span class="line">    &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;</span><br><span class="line">    &lt;version&gt;1.5.6.RELEASE&lt;/version&gt;</span><br><span class="line">&lt;/parent&gt;</span><br></pre></td></tr></table></figure>
<h4 id="2-导入spring-boot-dependencies项目依赖"><a href="#2-导入spring-boot-dependencies项目依赖" class="headerlink" title="2. 导入spring-boot-dependencies项目依赖"></a>2. 导入spring-boot-dependencies项目依赖</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">&lt;dependencyManagement&gt;</span><br><span class="line">	&lt;dependencies&gt;</span><br><span class="line">		&lt;dependency&gt;</span><br><span class="line">			&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">			&lt;artifactId&gt;spring-boot-dependencies&lt;/artifactId&gt;</span><br><span class="line">			&lt;version&gt;1.5.6.RELEASE&lt;/version&gt;</span><br><span class="line">			&lt;type&gt;pom&lt;/type&gt;</span><br><span class="line">			&lt;scope&gt;import&lt;/scope&gt;</span><br><span class="line">		&lt;/dependency&gt;</span><br><span class="line">&lt;/dependencyManagement&gt;</span><br></pre></td></tr></table></figure>
<h2 id="Spring-Boot依赖注意点"><a href="#Spring-Boot依赖注意点" class="headerlink" title="Spring Boot依赖注意点"></a>Spring Boot依赖注意点</h2><h3 id="1-属性覆盖只对继承有效"><a href="#1-属性覆盖只对继承有效" class="headerlink" title="1. 属性覆盖只对继承有效"></a>1. 属性覆盖只对继承有效</h3><blockquote>
<p>This only works if your Maven project inherits (directly or indirectly) from spring-boot-dependencies. If you have added spring-boot-dependencies in your own dependencyManagement section with <scope>import</scope> you have to redefine the artifact yourself instead of overriding the property.</p>
</blockquote>
<p>Spring Boot依赖包里面的组件的版本都是和当前Spring Boot绑定的，如果要修改里面组件的版本，只需要添加如下属性覆盖即可，但这种方式只对继承有效，导入的方式无效。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&lt;properties&gt;</span><br><span class="line">    &lt;slf4j.version&gt;1.7.25&lt;slf4j.version&gt;</span><br><span class="line">&lt;/properties&gt;</span><br></pre></td></tr></table></figure>
<p>如果导入的方式要实现版本的升级，达到上面的效果，这样也可以做到，把要升级的组件依赖放到Spring Boot之前。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">&lt;dependencyManagement&gt;</span><br><span class="line">    &lt;dependencies&gt;</span><br><span class="line">        &lt;!-- Override Spring Data release train provided by Spring Boot --&gt;</span><br><span class="line">        &lt;dependency&gt;</span><br><span class="line">            &lt;groupId&gt;org.springframework.data&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;spring-data-releasetrain&lt;/artifactId&gt;</span><br><span class="line">            &lt;version&gt;Fowler-SR2&lt;/version&gt;</span><br><span class="line">            &lt;scope&gt;import&lt;/scope&gt;</span><br><span class="line">            &lt;type&gt;pom&lt;/type&gt;</span><br><span class="line">        &lt;/dependency&gt;</span><br><span class="line">        &lt;dependency&gt;</span><br><span class="line">            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;spring-boot-dependencies&lt;/artifactId&gt;</span><br><span class="line">            &lt;version&gt;1.5.6.RELEASE&lt;/version&gt;</span><br><span class="line">            &lt;type&gt;pom&lt;/type&gt;</span><br><span class="line">            &lt;scope&gt;import&lt;/scope&gt;</span><br><span class="line">        &lt;/dependency&gt;</span><br><span class="line">    &lt;/dependencies&gt;</span><br><span class="line">&lt;/dependencyManagement&gt;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>Each Spring Boot release is designed and tested against a specific set of third-party dependencies. Overriding versions may cause compatibility issues.</p>
</blockquote>
<p>需要注意，要修改Spring Boot的依赖组件版本可能会造成不兼容的问题。</p>
<h3 id="2-资源文件过滤问题"><a href="#2-资源文件过滤问题" class="headerlink" title="2. 资源文件过滤问题"></a>2. 资源文件过滤问题</h3><p>使用继承Spring Boot时，如果要使用Maven resource filter过滤资源文件时，资源文件里面的占位符为了使${}和Spring Boot区别开来，此时要用@...@包起来，不然无效。另外，@...@占位符在yaml文件编辑器中编译报错，所以使用继承方式有诸多问题，坑要慢慢趟。</p>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">



</div>

    <a data-url="http://youanyyou.gitee.io/javastack/2018/04/18/Spring Boot/Spring Boot开启的2种方式/" data-id="cjg4zd8oa0044hg8ak4zzesnx" class="article-share-link"><i class="fa fa-share"></i>分享到</a>
<script>
    (function ($) {
        // Prevent duplicate binding
        if (typeof(__SHARE_BUTTON_BINDED__) === 'undefined' || !__SHARE_BUTTON_BINDED__) {
            __SHARE_BUTTON_BINDED__ = true;
        } else {
            return;
        }
        $('body').on('click', function() {
            $('.article-share-box.on').removeClass('on');
        }).on('click', '.article-share-link', function(e) {
            e.stopPropagation();

            var $this = $(this),
                url = $this.attr('data-url'),
                encodedUrl = encodeURIComponent(url),
                id = 'article-share-box-' + $this.attr('data-id'),
                offset = $this.offset(),
                box;

            if ($('#' + id).length) {
                box = $('#' + id);

                if (box.hasClass('on')){
                    box.removeClass('on');
                    return;
                }
            } else {
                var html = [
                    '<div id="' + id + '" class="article-share-box">',
                        '<input class="article-share-input" value="' + url + '">',
                        '<div class="article-share-links">',
                            '<a href="https://twitter.com/intent/tweet?url=' + encodedUrl + '" class="fa fa-twitter article-share-twitter" target="_blank" title="Twitter"></a>',
                            '<a href="https://www.facebook.com/sharer.php?u=' + encodedUrl + '" class="fa fa-facebook article-share-facebook" target="_blank" title="Facebook"></a>',
                            '<a href="http://pinterest.com/pin/create/button/?url=' + encodedUrl + '" class="fa fa-pinterest article-share-pinterest" target="_blank" title="Pinterest"></a>',
                            '<a href="https://plus.google.com/share?url=' + encodedUrl + '" class="fa fa-google article-share-google" target="_blank" title="Google+"></a>',
                        '</div>',
                    '</div>'
                ].join('');

              box = $(html);

              $('body').append(box);
            }

            $('.article-share-box.on').hide();

            box.css({
                top: offset.top + 25,
                left: offset.left
            }).addClass('on');

        }).on('click', '.article-share-box', function (e) {
            e.stopPropagation();
        }).on('click', '.article-share-box-input', function () {
            $(this).select();
        }).on('click', '.article-share-box-link', function (e) {
            e.preventDefault();
            e.stopPropagation();

            window.open(this.href, 'article-share-box-window-' + Date.now(), 'width=500,height=450');
        });
    })(jQuery);
</script>

            
    

        </footer>
    </div>
    
</article>



    <article id="post-Spring Boot/Spring Boot实现热部署" class="article article-type-post" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <p>在Spring Boot实现代码热部署是一件很简单的事情，代码的修改可以自动部署并重新热启动项目。</p>
<h2 id="引用devtools依赖"><a href="#引用devtools依赖" class="headerlink" title="引用devtools依赖"></a>引用devtools依赖</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;dependency&gt;</span><br><span class="line">    &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;spring-boot-devtools&lt;/artifactId&gt;</span><br><span class="line">    &lt;optional&gt;true&lt;/optional&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br></pre></td></tr></table></figure>
<p>这样，当修改一个java类时就会热更新。</p>
<h2 id="自定义配置热部署"><a href="#自定义配置热部署" class="headerlink" title="自定义配置热部署"></a>自定义配置热部署</h2><p>以下配置用于自定义配置热部署，可以不设置。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"># 热部署开关，false即不启用热部署</span><br><span class="line">spring.devtools.restart.enabled: true</span><br><span class="line"></span><br><span class="line"># 指定热部署的目录</span><br><span class="line">#spring.devtools.restart.additional-paths: src/main/java</span><br><span class="line"></span><br><span class="line"># 指定目录不更新</span><br><span class="line">spring.devtools.restart.exclude: test/**</span><br></pre></td></tr></table></figure>
<h2 id="Intellij-Idea修改"><a href="#Intellij-Idea修改" class="headerlink" title="Intellij Idea修改"></a>Intellij Idea修改</h2><p>如果是idea，需要改以下两个地方：</p>
<p>1、勾上自动编译或者手动重新编译</p>
<blockquote>
<p>File &gt; Settings &gt; Compiler-Build Project automatically</p>
</blockquote>
<p>2、注册</p>
<blockquote>
<p>ctrl + shift + alt + / &gt; Registry &gt; 勾选Compiler autoMake allow when app running</p>
</blockquote>
<h2 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h2><p>1、生产环境devtools将被禁用，如java -jar方式或者自定义的类加载器等都会识别为生产环境。</p>
<p>2、打包应用默认不会包含devtools，除非你禁用SpringBoot Maven插件的<code>excludeDevtools</code>属性。</p>
<p>3、Thymeleaf无需配置<code>spring.thymeleaf.cache: false</code>，devtools默认会自动设置，<a href="https://github.com/spring-projects/spring-boot/blob/v1.5.7.RELEASE/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/env/DevToolsPropertyDefaultsPostProcessor.java" target="_blank" rel="noopener">点击</a>参考完整属性。</p>
<p>下面是devtools自动配置的部分源码：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">@Order(Ordered.LOWEST_PRECEDENCE)</span><br><span class="line">public class DevToolsPropertyDefaultsPostProcessor implements EnvironmentPostProcessor &#123;</span><br><span class="line"></span><br><span class="line">	private static final Map&lt;String, Object&gt; PROPERTIES;</span><br><span class="line"></span><br><span class="line">	static &#123;</span><br><span class="line">		Map&lt;String, Object&gt; properties = new HashMap&lt;String, Object&gt;();</span><br><span class="line">		properties.put(&quot;spring.thymeleaf.cache&quot;, &quot;false&quot;);</span><br><span class="line">		properties.put(&quot;spring.freemarker.cache&quot;, &quot;false&quot;);</span><br><span class="line">		properties.put(&quot;spring.groovy.template.cache&quot;, &quot;false&quot;);</span><br><span class="line">		properties.put(&quot;spring.mustache.cache&quot;, &quot;false&quot;);</span><br><span class="line">		properties.put(&quot;server.session.persistent&quot;, &quot;true&quot;);</span><br><span class="line">		properties.put(&quot;spring.h2.console.enabled&quot;, &quot;true&quot;);</span><br><span class="line">		properties.put(&quot;spring.resources.cache-period&quot;, &quot;0&quot;);</span><br><span class="line">		properties.put(&quot;spring.resources.chain.cache&quot;, &quot;false&quot;);</span><br><span class="line">		properties.put(&quot;spring.template.provider.cache&quot;, &quot;false&quot;);</span><br><span class="line">		properties.put(&quot;spring.mvc.log-resolved-exception&quot;, &quot;true&quot;);</span><br><span class="line">		properties.put(&quot;server.jsp-servlet.init-parameters.development&quot;, &quot;true&quot;);</span><br><span class="line">		PROPERTIES = Collections.unmodifiableMap(properties);</span><br><span class="line">	&#125;</span><br></pre></td></tr></table></figure>
<p>4、devtools会在windows资源管理器占用java进程，在开发工具里面杀不掉，只能手动kill掉，不然重启会选成端口重复绑定报错。</p>
<p>关于boot-devtools更多详细用法，<a href="https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-devtools.html" target="_blank" rel="noopener">点击</a>参考官方文档。</p>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">



</div>

    <a data-url="http://youanyyou.gitee.io/javastack/2018/04/18/Spring Boot/Spring Boot实现热部署/" data-id="cjg4zd8o6003zhg8aa6aojy41" class="article-share-link"><i class="fa fa-share"></i>分享到</a>
<script>
    (function ($) {
        // Prevent duplicate binding
        if (typeof(__SHARE_BUTTON_BINDED__) === 'undefined' || !__SHARE_BUTTON_BINDED__) {
            __SHARE_BUTTON_BINDED__ = true;
        } else {
            return;
        }
        $('body').on('click', function() {
            $('.article-share-box.on').removeClass('on');
        }).on('click', '.article-share-link', function(e) {
            e.stopPropagation();

            var $this = $(this),
                url = $this.attr('data-url'),
                encodedUrl = encodeURIComponent(url),
                id = 'article-share-box-' + $this.attr('data-id'),
                offset = $this.offset(),
                box;

            if ($('#' + id).length) {
                box = $('#' + id);

                if (box.hasClass('on')){
                    box.removeClass('on');
                    return;
                }
            } else {
                var html = [
                    '<div id="' + id + '" class="article-share-box">',
                        '<input class="article-share-input" value="' + url + '">',
                        '<div class="article-share-links">',
                            '<a href="https://twitter.com/intent/tweet?url=' + encodedUrl + '" class="fa fa-twitter article-share-twitter" target="_blank" title="Twitter"></a>',
                            '<a href="https://www.facebook.com/sharer.php?u=' + encodedUrl + '" class="fa fa-facebook article-share-facebook" target="_blank" title="Facebook"></a>',
                            '<a href="http://pinterest.com/pin/create/button/?url=' + encodedUrl + '" class="fa fa-pinterest article-share-pinterest" target="_blank" title="Pinterest"></a>',
                            '<a href="https://plus.google.com/share?url=' + encodedUrl + '" class="fa fa-google article-share-google" target="_blank" title="Google+"></a>',
                        '</div>',
                    '</div>'
                ].join('');

              box = $(html);

              $('body').append(box);
            }

            $('.article-share-box.on').hide();

            box.css({
                top: offset.top + 25,
                left: offset.left
            }).addClass('on');

        }).on('click', '.article-share-box', function (e) {
            e.stopPropagation();
        }).on('click', '.article-share-box-input', function () {
            $(this).select();
        }).on('click', '.article-share-box-link', function (e) {
            e.preventDefault();
            e.stopPropagation();

            window.open(this.href, 'article-share-box-window-' + Date.now(), 'width=500,height=450');
        });
    })(jQuery);
</script>

            
    

        </footer>
    </div>
    
</article>



    <article id="post-Spring Boot/Spring Boot日志集成" class="article article-type-post" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <h2 id="Spring-Boot日志框架"><a href="#Spring-Boot日志框架" class="headerlink" title="Spring Boot日志框架"></a>Spring Boot日志框架</h2><p>Spring Boot支持Java Util Logging,Log4j2,Lockback作为日志框架，如果你使用starters启动器，Spring Boot将使用Logback作为默认日志框架。无论使用哪种日志框架，Spring Boot都支持配置将日志输出到控制台或者文件中。</p>
<p>spring-boot-starter启动器包含spring-boot-starter-logging启动器并集成了slf4j日志抽象及Logback日志框架。</p>
<h2 id="属性配置日志"><a href="#属性配置日志" class="headerlink" title="属性配置日志"></a>属性配置日志</h2><p>Spring Boot支持属性配置日志参数，这个不是很灵活，不细讲。</p>
<p>参考配置：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"># LOGGING</span><br><span class="line">logging.config= # Location of the logging configuration file. For instance `classpath:logback.xml` for Logback</span><br><span class="line">logging.exception-conversion-word=%wEx # Conversion word used when logging exceptions.</span><br><span class="line">logging.file= # Log file name. For instance `myapp.log`</span><br><span class="line">logging.level.*= # Log levels severity mapping. For instance `logging.level.org.springframework=DEBUG`</span><br><span class="line">logging.path= # Location of the log file. For instance `/var/log`</span><br><span class="line">logging.pattern.console= # Appender pattern for output to the console. Only supported with the default logback setup.</span><br><span class="line">logging.pattern.file= # Appender pattern for output to the file. Only supported with the default logback setup.</span><br><span class="line">logging.pattern.level= # Appender pattern for log level (default %5p). Only supported with the default logback setup.</span><br><span class="line">logging.register-shutdown-hook=false # Register a shutdown hook for the logging system when it is initialized.</span><br></pre></td></tr></table></figure>
<p>如：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">logging.level.root=DEBUG</span><br><span class="line">logging.level.org.springframework.web=DEBUG</span><br><span class="line">logging.level.org.hibernate=ERROR</span><br></pre></td></tr></table></figure>
<h2 id="自定义日志文件"><a href="#自定义日志文件" class="headerlink" title="自定义日志文件"></a>自定义日志文件</h2><p>根据不同的日志框架，默认加载的日志配置文件的文件名，放在资源根目录下，其他的目录及文件名不能被加载。</p>
<table>
<thead>
<tr>
<th>Logging System</th>
<th>Customization</th>
</tr>
</thead>
<tbody>
<tr>
<td>Logback</td>
<td>logback-spring.xml, logback-spring.groovy, logback.xml or logback.groovy</td>
</tr>
<tr>
<td>Log4j2</td>
<td>log4j2-spring.xml or log4j2.xml</td>
</tr>
<tr>
<td>JDK (Java Util Logging)</td>
<td>logging.properties</td>
</tr>
</tbody>
</table>
<p>既然默认自带了Logback框架，Logback也是最优秀的日志框架，往资源目录下创建一个logback-spring.xml即可，下面是一个参考配置文件。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br></pre></td><td class="code"><pre><span class="line">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span><br><span class="line">&lt;configuration debug=&quot;false&quot;&gt;</span><br><span class="line"></span><br><span class="line">	&lt;springProperty scope=&quot;context&quot; name=&quot;APP_NAME&quot; source=&quot;spring.application.name&quot;/&gt;</span><br><span class="line">	&lt;springProperty scope=&quot;context&quot; name=&quot;APP_PORT&quot; source=&quot;server.port&quot;/&gt;</span><br><span class="line">	&lt;springProperty scope=&quot;context&quot; name=&quot;DEFAULT_APP_PORT&quot; source=&quot;spring.application.port&quot;/&gt;</span><br><span class="line"></span><br><span class="line">	&lt;property name=&quot;OS_NAME&quot; value=&quot;$&#123;os.name&#125;&quot;/&gt;</span><br><span class="line">	&lt;if condition=&apos;property(&quot;OS_NAME&quot;).contains(&quot;Windows&quot;)&apos;&gt;</span><br><span class="line">		&lt;then&gt;</span><br><span class="line">			&lt;property name=&quot;LOG_PATH&quot; value=&quot;$&#123;LOG_PATH:-E:/logs&#125;&quot; /&gt;</span><br><span class="line">		&lt;/then&gt;</span><br><span class="line">		&lt;else&gt;</span><br><span class="line">			&lt;property name=&quot;LOG_PATH&quot; value=&quot;$&#123;LOG_PATH:-/log&#125;&quot; /&gt;</span><br><span class="line">		&lt;/else&gt;</span><br><span class="line">	&lt;/if&gt;    	</span><br><span class="line">    </span><br><span class="line">	&lt;property name=&quot;LOG_DIR&quot; value=&quot;$&#123;APP_NAME:-system&#125;&quot; /&gt;</span><br><span class="line">	&lt;property name=&quot;APP_PORT&quot; value=&quot;$&#123;APP_PORT:-$&#123;DEFAULT_APP_PORT:-0&#125;&#125;&quot; /&gt;</span><br><span class="line">	&lt;if condition=&apos;!property(&quot;APP_PORT&quot;).equals(&quot;0&quot;)&apos;&gt;</span><br><span class="line">		&lt;then&gt;</span><br><span class="line">			&lt;property name=&quot;LOG_DIR&quot; value=&quot;$&#123;LOG_DIR&#125;-$&#123;APP_PORT&#125;&quot; /&gt;</span><br><span class="line">		&lt;/then&gt;</span><br><span class="line">	&lt;/if&gt;</span><br><span class="line"></span><br><span class="line">	</span><br><span class="line">	&lt;!-- 控制台输出 --&gt;</span><br><span class="line">	&lt;appender name=&quot;STDOUT&quot; class=&quot;ch.qos.logback.core.ConsoleAppender&quot;&gt;</span><br><span class="line">		&lt;encoder class=&quot;ch.qos.logback.classic.encoder.PatternLayoutEncoder&quot;&gt;</span><br><span class="line">			&lt;!--格式化输出：%d表示日期，%thread表示线程名，%-5level：级别从左显示5个字符宽度，%msg：日志消息，%n是换行符 --&gt;</span><br><span class="line">			&lt;pattern&gt;%d&#123;yyyy-MM-dd HH:mm:ss.SSS&#125; [%thread] %-5level %logger&#123;50&#125; - %msg%n&lt;/pattern&gt;</span><br><span class="line">		&lt;/encoder&gt;</span><br><span class="line">	&lt;/appender&gt;</span><br><span class="line">	</span><br><span class="line">	&lt;!-- 按照每天生成日志文件 --&gt;</span><br><span class="line">	&lt;appender name=&quot;FILE&quot; class=&quot;ch.qos.logback.core.rolling.RollingFileAppender&quot;&gt;</span><br><span class="line">		&lt;filter class=&quot;ch.qos.logback.classic.filter.ThresholdFilter&quot;&gt;</span><br><span class="line">			&lt;level&gt;INFO&lt;/level&gt;</span><br><span class="line">		&lt;/filter&gt;</span><br><span class="line">		&lt;rollingPolicy class=&quot;ch.qos.logback.core.rolling.TimeBasedRollingPolicy&quot;&gt;</span><br><span class="line">			&lt;!--日志文件输出的文件名 --&gt;</span><br><span class="line">			&lt;FileNamePattern&gt;$&#123;LOG_PATH&#125;/$&#123;LOG_DIR&#125;/info.log.%d&#123;yyyy-MM-dd&#125;.log&lt;/FileNamePattern&gt;</span><br><span class="line">			</span><br><span class="line">			&lt;!--日志文件保留天数 --&gt;</span><br><span class="line">			&lt;MaxHistory&gt;30&lt;/MaxHistory&gt;</span><br><span class="line">		&lt;/rollingPolicy&gt;</span><br><span class="line">		</span><br><span class="line">		&lt;encoder class=&quot;ch.qos.logback.classic.encoder.PatternLayoutEncoder&quot;&gt;</span><br><span class="line">			&lt;!--格式化输出：%d表示日期，%thread表示线程名，%-5level：级别从左显示5个字符宽度%msg：日志消息，%n是换行符 --&gt;</span><br><span class="line">			&lt;pattern&gt;%d&#123;yyyy-MM-dd HH:mm:ss.SSS&#125; [%thread] %-5level %logger&#123;50&#125; - %msg%n&lt;/pattern&gt;</span><br><span class="line">		&lt;/encoder&gt;</span><br><span class="line">		</span><br><span class="line">		&lt;!--日志文件最大的大小 --&gt;</span><br><span class="line">		&lt;triggeringPolicy class=&quot;ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy&quot;&gt;</span><br><span class="line">			&lt;MaxFileSize&gt;10MB&lt;/MaxFileSize&gt;</span><br><span class="line">		&lt;/triggeringPolicy&gt;</span><br><span class="line">		</span><br><span class="line">	&lt;/appender&gt;</span><br><span class="line">	</span><br><span class="line">	&lt;!-- 按照每天生成日志文件 error级别 --&gt;</span><br><span class="line">	&lt;appender name=&quot;FILE-ERROR&quot; class=&quot;ch.qos.logback.core.rolling.RollingFileAppender&quot;&gt;</span><br><span class="line">		&lt;filter class=&quot;ch.qos.logback.classic.filter.LevelFilter&quot;&gt;</span><br><span class="line">			&lt;level&gt;ERROR&lt;/level&gt;</span><br><span class="line">			&lt;onMatch&gt;ACCEPT&lt;/onMatch&gt;</span><br><span class="line">			&lt;onMismatch&gt;DENY&lt;/onMismatch&gt;</span><br><span class="line">		&lt;/filter&gt;   </span><br><span class="line">		&lt;rollingPolicy class=&quot;ch.qos.logback.core.rolling.TimeBasedRollingPolicy&quot;&gt;</span><br><span class="line">			&lt;!--日志文件输出的文件名 --&gt;</span><br><span class="line">			&lt;FileNamePattern&gt;$&#123;LOG_PATH&#125;/$&#123;LOG_DIR&#125;/error.log.%d&#123;yyyy-MM-dd&#125;.log&lt;/FileNamePattern&gt;</span><br><span class="line">			</span><br><span class="line">			&lt;!--日志文件保留天数 --&gt;</span><br><span class="line">			&lt;MaxHistory&gt;30&lt;/MaxHistory&gt;</span><br><span class="line">		&lt;/rollingPolicy&gt;</span><br><span class="line">		</span><br><span class="line">		&lt;encoder class=&quot;ch.qos.logback.classic.encoder.PatternLayoutEncoder&quot;&gt;</span><br><span class="line">			&lt;!--格式化输出：%d表示日期，%thread表示线程名，%-5level：级别从左显示5个字符宽度%msg：日志消息，%n是换行符 --&gt;</span><br><span class="line">			&lt;pattern&gt;%d&#123;yyyy-MM-dd HH:mm:ss.SSS&#125; [%thread] %-5level %logger&#123;50&#125; - %msg%n&lt;/pattern&gt;</span><br><span class="line">		&lt;/encoder&gt;</span><br><span class="line">		</span><br><span class="line">		&lt;!--日志文件最大的大小 --&gt;</span><br><span class="line">		&lt;triggeringPolicy class=&quot;ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy&quot;&gt;</span><br><span class="line">			&lt;MaxFileSize&gt;10MB&lt;/MaxFileSize&gt;</span><br><span class="line">		&lt;/triggeringPolicy&gt;</span><br><span class="line">		</span><br><span class="line">	&lt;/appender&gt;</span><br><span class="line"></span><br><span class="line">	&lt;!--myibatis log configure --&gt;</span><br><span class="line">	&lt;logger name=&quot;com.apache.ibatis&quot; level=&quot;TRACE&quot; /&gt;</span><br><span class="line">	&lt;logger name=&quot;java.sql.Connection&quot; level=&quot;DEBUG&quot; /&gt;</span><br><span class="line">	&lt;logger name=&quot;java.sql.Statement&quot; level=&quot;DEBUG&quot; /&gt;</span><br><span class="line">	&lt;logger name=&quot;java.sql.PreparedStatement&quot; level=&quot;DEBUG&quot; /&gt;</span><br><span class="line"></span><br><span class="line">	&lt;!-- 日志输出级别 --&gt;</span><br><span class="line">	&lt;root level=&quot;INFO&quot;&gt;</span><br><span class="line">		&lt;appender-ref ref=&quot;STDOUT&quot; /&gt;</span><br><span class="line">		&lt;appender-ref ref=&quot;FILE&quot; /&gt;</span><br><span class="line">		&lt;appender-ref ref=&quot;FILE-ERROR&quot; /&gt;</span><br><span class="line">	&lt;/root&gt;</span><br><span class="line">	</span><br><span class="line">&lt;/configuration&gt;</span><br></pre></td></tr></table></figure>
<p>强烈推荐使用logback-spring.xml作为文件名，因为logback.xml加载太早。</p>
<p>日志初始化在ApplicationContext创建之前，所以@PropertySources加载的配置是读取不到的，系统环境变量、Spring Environment及application,bootstrap配置文件中的信息可以读取到。</p>
<p>读取系统环境属性：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;property name=&quot;LOG_PATH&quot; value=&quot;$&#123;LOG_PATH:-E:/logs&#125;&quot; /&gt;</span><br></pre></td></tr></table></figure>
<p>读取当前应用Environment中的属性：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&lt;springProperty scope=&quot;context&quot; name=&quot;fluentHost&quot; source=&quot;myapp.fluentd.host&quot;</span><br><span class="line">        defaultValue=&quot;localhost&quot;/&gt;</span><br></pre></td></tr></table></figure>
<p>Spring Boot也支持通过springProfile来加载不同profiles下的配置。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">&lt;springProfile name=&quot;staging&quot;&gt;</span><br><span class="line">    &lt;!-- configuration to be enabled when the &quot;staging&quot; profile is active --&gt;</span><br><span class="line">&lt;/springProfile&gt;</span><br><span class="line"></span><br><span class="line">&lt;springProfile name=&quot;dev, staging&quot;&gt;</span><br><span class="line">    &lt;!-- configuration to be enabled when the &quot;dev&quot; or &quot;staging&quot; profiles are active --&gt;</span><br><span class="line">&lt;/springProfile&gt;</span><br><span class="line"></span><br><span class="line">&lt;springProfile name=&quot;!production&quot;&gt;</span><br><span class="line">    &lt;!-- configuration to be enabled when the &quot;production&quot; profile is not active --&gt;</span><br><span class="line">&lt;/springProfile&gt;</span><br></pre></td></tr></table></figure>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">



</div>

    <a data-url="http://youanyyou.gitee.io/javastack/2018/04/18/Spring Boot/Spring Boot日志集成/" data-id="cjg4zd8of0049hg8ayf3oawkc" class="article-share-link"><i class="fa fa-share"></i>分享到</a>
<script>
    (function ($) {
        // Prevent duplicate binding
        if (typeof(__SHARE_BUTTON_BINDED__) === 'undefined' || !__SHARE_BUTTON_BINDED__) {
            __SHARE_BUTTON_BINDED__ = true;
        } else {
            return;
        }
        $('body').on('click', function() {
            $('.article-share-box.on').removeClass('on');
        }).on('click', '.article-share-link', function(e) {
            e.stopPropagation();

            var $this = $(this),
                url = $this.attr('data-url'),
                encodedUrl = encodeURIComponent(url),
                id = 'article-share-box-' + $this.attr('data-id'),
                offset = $this.offset(),
                box;

            if ($('#' + id).length) {
                box = $('#' + id);

                if (box.hasClass('on')){
                    box.removeClass('on');
                    return;
                }
            } else {
                var html = [
                    '<div id="' + id + '" class="article-share-box">',
                        '<input class="article-share-input" value="' + url + '">',
                        '<div class="article-share-links">',
                            '<a href="https://twitter.com/intent/tweet?url=' + encodedUrl + '" class="fa fa-twitter article-share-twitter" target="_blank" title="Twitter"></a>',
                            '<a href="https://www.facebook.com/sharer.php?u=' + encodedUrl + '" class="fa fa-facebook article-share-facebook" target="_blank" title="Facebook"></a>',
                            '<a href="http://pinterest.com/pin/create/button/?url=' + encodedUrl + '" class="fa fa-pinterest article-share-pinterest" target="_blank" title="Pinterest"></a>',
                            '<a href="https://plus.google.com/share?url=' + encodedUrl + '" class="fa fa-google article-share-google" target="_blank" title="Google+"></a>',
                        '</div>',
                    '</div>'
                ].join('');

              box = $(html);

              $('body').append(box);
            }

            $('.article-share-box.on').hide();

            box.css({
                top: offset.top + 25,
                left: offset.left
            }).addClass('on');

        }).on('click', '.article-share-box', function (e) {
            e.stopPropagation();
        }).on('click', '.article-share-box-input', function () {
            $(this).select();
        }).on('click', '.article-share-box-link', function (e) {
            e.preventDefault();
            e.stopPropagation();

            window.open(this.href, 'article-share-box-window-' + Date.now(), 'width=500,height=450');
        });
    })(jQuery);
</script>

            
    

        </footer>
    </div>
    
</article>



    <article id="post-Spring Boot/Spring Boot集成Mybatis双数据源" class="article article-type-post" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <p>这里用到了Spring Boot + Mybatis + DynamicDataSource配置动态双数据源，可以动态切换数据源实现数据库的读写分离。</p>
<h2 id="添加依赖"><a href="#添加依赖" class="headerlink" title="添加依赖"></a>添加依赖</h2><p>加入Mybatis启动器，这里添加了Druid连接池、Oracle数据库驱动为例。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">&lt;dependency&gt;</span><br><span class="line">	&lt;groupId&gt;org.mybatis.spring.boot&lt;/groupId&gt;</span><br><span class="line">	&lt;artifactId&gt;mybatis-spring-boot-starter&lt;/artifactId&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br><span class="line"></span><br><span class="line">&lt;dependency&gt;</span><br><span class="line">	&lt;groupId&gt;com.alibaba&lt;/groupId&gt;</span><br><span class="line">	&lt;artifactId&gt;druid&lt;/artifactId&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br><span class="line"></span><br><span class="line">&lt;dependency&gt;</span><br><span class="line">	&lt;groupId&gt;com.oracle&lt;/groupId&gt;</span><br><span class="line">	&lt;artifactId&gt;ojdbc6&lt;/artifactId&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br></pre></td></tr></table></figure>
<h2 id="添加启动类"><a href="#添加启动类" class="headerlink" title="添加启动类"></a>添加启动类</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">@EnableMybatis</span><br><span class="line">@EnableTransactionManagement</span><br><span class="line">@SpringBootApplication(exclude = &#123; DataSourceAutoConfiguration.class &#125;)</span><br><span class="line">public class Application &#123;</span><br><span class="line"></span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		SpringApplication.run(ServiceApplication.class, args);</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })：<br>这里用到了双数据源，需要排除数据源的自动配置，如果只有一个数据源用Spring Boot的自动配置就行。</p>
<p>@EnableTransactionManagement：开启事务支持。</p>
<p>@EnableMybatis：开启Mybatis功能</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">@Target(ElementType.TYPE)</span><br><span class="line">@Retention(RetentionPolicy.RUNTIME)</span><br><span class="line">@Documented</span><br><span class="line">@Import(MybatisConfig.class)</span><br><span class="line">public @interface EnableMybatis &#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="Mybatis配置类"><a href="#Mybatis配置类" class="headerlink" title="Mybatis配置类"></a>Mybatis配置类</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line">@Configuration</span><br><span class="line">@MapperScan(basePackages = DSConfig.BASE_PACKAGES)</span><br><span class="line">public class MybatisConfig implements DSConfig &#123;</span><br><span class="line"></span><br><span class="line">	@Primary</span><br><span class="line">	@Bean</span><br><span class="line">	public DynamicDataSource dynamicDataSource(@Qualifier(DB_MASTER) DataSource master,</span><br><span class="line">			@Qualifier(DB_SLAVE) DataSource slave) &#123;</span><br><span class="line">		Map&lt;Object, Object&gt; dsMap = new HashMap&lt;&gt;();</span><br><span class="line">		dsMap.put(DB_MASTER, master);</span><br><span class="line">		dsMap.put(DB_MASTER, slave);</span><br><span class="line"></span><br><span class="line">		DynamicDataSource dynamicDataSource = new DynamicDataSource();</span><br><span class="line">		dynamicDataSource.setDefaultTargetDataSource(master);</span><br><span class="line">		dynamicDataSource.setTargetDataSources(dsMap);</span><br><span class="line">		return dynamicDataSource;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	@Bean</span><br><span class="line">	public PlatformTransactionManager transactionManager(DynamicDataSource dynamicDataSource) &#123;</span><br><span class="line">		return new DataSourceTransactionManager(dynamicDataSource);</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	@Bean</span><br><span class="line">	public SqlSessionFactory sqlSessionFactory(DynamicDataSource dynamicDataSource)</span><br><span class="line">			throws Exception &#123;</span><br><span class="line">		SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();</span><br><span class="line">		sessionFactory.setDataSource(dynamicDataSource);</span><br><span class="line">		sessionFactory.setMapperLocations(</span><br><span class="line">				((ResourcePatternResolver) new PathMatchingResourcePatternResolver())</span><br><span class="line">						.getResources(DSConfig.MAPPER_LOCATIONS));</span><br><span class="line">		return sessionFactory.getObject();</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>DSConfig常量类：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">public interface DSConfig &#123;</span><br><span class="line"></span><br><span class="line">	String DS_PREFIX = &quot;spring.datasource&quot;;</span><br><span class="line">	String DS_ACTIVE = &quot;active&quot;;</span><br><span class="line"></span><br><span class="line">	String DB_MASTER = &quot;db-master&quot;;</span><br><span class="line">	String DB_SLAVE = &quot;db-slave&quot;;</span><br><span class="line"></span><br><span class="line">	String DRUID = &quot;druid&quot;;</span><br><span class="line"></span><br><span class="line">	String DRUID_MONITOR_USERNAME = &quot;spring.druid.username&quot;;</span><br><span class="line">	String DRUID_MONITOR_PASSWORD = &quot;spring.druid.password&quot;;</span><br><span class="line">	String DRUID_MONITOR_URL = &quot;/druid/*&quot;;</span><br><span class="line">	String DRUID_FILTER_EXCLUSIONS = &quot;*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*&quot;;</span><br><span class="line">	String DRUID_FILTER_URL = &quot;/*&quot;;</span><br><span class="line"></span><br><span class="line">	String BASE_PACKAGES = &quot;com.example.**.mapper&quot;;</span><br><span class="line">	String MAPPER_LOCATIONS = &quot;mapper/**/*.xml&quot;;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="连接池配置类"><a href="#连接池配置类" class="headerlink" title="连接池配置类"></a>连接池配置类</h2><p>Druid连接池的自动配置类：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br></pre></td><td class="code"><pre><span class="line">@Configuration</span><br><span class="line">@Import(&#123; PropertiesConfig.class &#125;)</span><br><span class="line">@ConditionalOnClass(DruidDataSource.class)</span><br><span class="line">@ConditionalOnProperty(prefix = DSConfig.DS_PREFIX, value = DSConfig.DS_ACTIVE, havingValue = DSConfig.DRUID)</span><br><span class="line">public class DruidAutoConfig implements DSConfig &#123;</span><br><span class="line"></span><br><span class="line">	private Logger logger = LoggerUtils.getLogger(this);</span><br><span class="line"></span><br><span class="line">	@Bean(name = DB_MASTER, initMethod = &quot;init&quot;, destroyMethod = &quot;close&quot;)</span><br><span class="line">	public DataSource dataSourceMaster(DruidMasterProperties masterProperties) throws SQLException &#123;</span><br><span class="line">		logger.debug(&quot;master properties: &#123;&#125;&quot;, masterProperties.toString());</span><br><span class="line"></span><br><span class="line">		DruidDataSource dds = new DruidDataSource();</span><br><span class="line">		dds.setDriverClassName(masterProperties.getDriverClassName());</span><br><span class="line">		dds.setUrl(masterProperties.getUrl());</span><br><span class="line">		dds.setUsername(masterProperties.getUsername());</span><br><span class="line">		dds.setPassword(masterProperties.getPassword());</span><br><span class="line">		dds.setInitialSize(masterProperties.getInitialSize());</span><br><span class="line">		dds.setMinIdle(masterProperties.getMinIdle());</span><br><span class="line">		dds.setMaxActive(masterProperties.getMaxActive());</span><br><span class="line">		dds.setMaxWait(masterProperties.getMaxWait());</span><br><span class="line">		dds.setTimeBetweenEvictionRunsMillis(masterProperties.getTimeBetweenEvictionRunsMillis());</span><br><span class="line">		dds.setMinEvictableIdleTimeMillis(masterProperties.getMinEvictableIdleTimeMillis());</span><br><span class="line">		dds.setValidationQuery(masterProperties.getValidationQuery());</span><br><span class="line">		dds.setTestOnBorrow(masterProperties.isTestOnBorrow());</span><br><span class="line">		dds.setTestWhileIdle(masterProperties.isTestWhileIdle());</span><br><span class="line">		dds.setTestOnReturn(masterProperties.isTestOnReturn());</span><br><span class="line">		dds.setPoolPreparedStatements(masterProperties.isPoolPreparedStatements());</span><br><span class="line">		dds.setMaxPoolPreparedStatementPerConnectionSize(</span><br><span class="line">				masterProperties.getMaxPoolPreparedStatementPerConnectionSize());</span><br><span class="line">		dds.setFilters(masterProperties.getFilters());</span><br><span class="line"></span><br><span class="line">		return dds;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	@Bean(name = DB_SLAVE, initMethod = &quot;init&quot;, destroyMethod = &quot;close&quot;)</span><br><span class="line">	public DataSource dataSourceSlave(DruidSlaveProperties slaveProperties) throws SQLException &#123;</span><br><span class="line">		logger.debug(&quot;slave properties: &#123;&#125;&quot;, slaveProperties.toString());</span><br><span class="line"></span><br><span class="line">		DruidDataSource dds = new DruidDataSource();</span><br><span class="line">		dds.setDriverClassName(slaveProperties.getDriverClassName());</span><br><span class="line">		dds.setUrl(slaveProperties.getUrl());</span><br><span class="line">		dds.setUsername(slaveProperties.getUsername());</span><br><span class="line">		dds.setPassword(slaveProperties.getPassword());</span><br><span class="line">		dds.setInitialSize(slaveProperties.getInitialSize());</span><br><span class="line">		dds.setMinIdle(slaveProperties.getMinIdle());</span><br><span class="line">		dds.setMaxActive(slaveProperties.getMaxActive());</span><br><span class="line">		dds.setMaxWait(slaveProperties.getMaxWait());</span><br><span class="line">		dds.setTimeBetweenEvictionRunsMillis(slaveProperties.getTimeBetweenEvictionRunsMillis());</span><br><span class="line">		dds.setMinEvictableIdleTimeMillis(slaveProperties.getMinEvictableIdleTimeMillis());</span><br><span class="line">		dds.setValidationQuery(slaveProperties.getValidationQuery());</span><br><span class="line">		dds.setTestOnBorrow(slaveProperties.isTestOnBorrow());</span><br><span class="line">		dds.setTestWhileIdle(slaveProperties.isTestWhileIdle());</span><br><span class="line">		dds.setTestOnReturn(slaveProperties.isTestOnReturn());</span><br><span class="line">		dds.setPoolPreparedStatements(slaveProperties.isPoolPreparedStatements());</span><br><span class="line">		dds.setMaxPoolPreparedStatementPerConnectionSize(</span><br><span class="line">				slaveProperties.getMaxPoolPreparedStatementPerConnectionSize());</span><br><span class="line">		dds.setFilters(slaveProperties.getFilters());</span><br><span class="line"></span><br><span class="line">		return dds;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	@Bean</span><br><span class="line">	public ServletRegistrationBean druidServletRegistrationBean(EnvConfig env) &#123;</span><br><span class="line">		String username = env.getStringValue(DSConfig.DRUID_MONITOR_USERNAME);</span><br><span class="line">		String password = env.getStringValue(DSConfig.DRUID_MONITOR_PASSWORD);</span><br><span class="line">		return new ServletRegistrationBean(new DruidStatViewServlet(username, password),</span><br><span class="line">				DSConfig.DRUID_MONITOR_URL);</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	@Bean</span><br><span class="line">	public FilterRegistrationBean druidFilterRegistrationBean() &#123;</span><br><span class="line">		WebStatFilter wsf = new WebStatFilter();</span><br><span class="line">		FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();</span><br><span class="line">		filterRegistrationBean.setFilter(wsf);</span><br><span class="line">		filterRegistrationBean.setUrlPatterns(Arrays.asList(DSConfig.DRUID_FILTER_URL));</span><br><span class="line">		filterRegistrationBean.setInitParameters(</span><br><span class="line">				Collections.singletonMap(&quot;exclusions&quot;, DSConfig.DRUID_FILTER_EXCLUSIONS));</span><br><span class="line">		return filterRegistrationBean;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>根据类路径下有DruidDataSource这个类即有Druid这个jar包和配置文件中spring.datasource.active=druid才开启对Druid连接池的自动配置。</p>
<p>导入的配置文件：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">@Configuration</span><br><span class="line">@ComponentScan(basePackages = &quot;com.example.common.config.properties&quot;)</span><br><span class="line">public class PropertiesConfig &#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>DruidMasterProperties、DruidSlaveProperties属性文件读取的配置省略。</p>
<p>连接池监控配置类：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line">public class DruidStatViewServlet extends StatViewServlet &#123;</span><br><span class="line"></span><br><span class="line">	private static final long serialVersionUID = 1L;</span><br><span class="line"></span><br><span class="line">	private String username;</span><br><span class="line">	private String password;</span><br><span class="line"></span><br><span class="line">	@Override</span><br><span class="line">	public String getInitParameter(String name) &#123;</span><br><span class="line">		if (&quot;loginUsername&quot;.equals(name)) &#123;</span><br><span class="line">			return username;</span><br><span class="line">		&#125;</span><br><span class="line"></span><br><span class="line">		if (&quot;loginPassword&quot;.equals(name)) &#123;</span><br><span class="line">			return password;</span><br><span class="line">		&#125;</span><br><span class="line"></span><br><span class="line">		return super.getInitParameter(name);</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	public DruidStatViewServlet(String username, String password) &#123;</span><br><span class="line">		super();</span><br><span class="line">		this.username = username;</span><br><span class="line">		this.password = password;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	public String getUsername() &#123;</span><br><span class="line">		return username;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	public String getPassword() &#123;</span><br><span class="line">		return password;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>在META-INF/spring.factories中加入Druid自动配置映射：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">org.springframework.boot.autoconfigure.EnableAutoConfiguration=\</span><br><span class="line">com.example.common.config.ds.DruidAutoConfig</span><br></pre></td></tr></table></figure>
<h2 id="切换数据源"><a href="#切换数据源" class="headerlink" title="切换数据源"></a>切换数据源</h2><p>切换数据源注解：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">@Target(ElementType.METHOD)</span><br><span class="line">@Retention(RetentionPolicy.RUNTIME)</span><br><span class="line">@Documented</span><br><span class="line">public @interface DS &#123;</span><br><span class="line">	String value() default DSConfig.DB_MASTER;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>动态数据源类：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">public class DynamicDataSource extends AbstractRoutingDataSource &#123;</span><br><span class="line"></span><br><span class="line">	private final Logger logger = LoggerUtils.getLogger(this);</span><br><span class="line"></span><br><span class="line">	@Override</span><br><span class="line">	protected Object determineCurrentLookupKey() &#123;</span><br><span class="line">		logger.debug(&quot;当前数据源为&#123;&#125;&quot;, DataSourceContextHolder.getDS());</span><br><span class="line">		return DataSourceContextHolder.getDS();</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>动态数据源AOP实现类：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">@Aspect</span><br><span class="line">@Component</span><br><span class="line">public class DynamicDataSourceAspect &#123;</span><br><span class="line"></span><br><span class="line">	@Before(&quot;@annotation(DS)&quot;)</span><br><span class="line">	public void beforeSwitchDS(JoinPoint point) &#123;</span><br><span class="line">		Class&lt;?&gt; className = point.getTarget().getClass();</span><br><span class="line">		String methodName = point.getSignature().getName();</span><br><span class="line">		Class&lt;?&gt;[] argClass = ((MethodSignature) point.getSignature()).getParameterTypes();</span><br><span class="line">		String dataSource = DataSourceContextHolder.DEFAULT_DS;</span><br><span class="line"></span><br><span class="line">		try &#123;</span><br><span class="line">			Method method = className.getMethod(methodName, argClass);</span><br><span class="line">			if (method.isAnnotationPresent(DS.class)) &#123;</span><br><span class="line">				DS annotation = method.getAnnotation(DS.class);</span><br><span class="line">				dataSource = annotation.value();</span><br><span class="line">			&#125;</span><br><span class="line">		&#125; catch (Exception e) &#123;</span><br><span class="line">			e.printStackTrace();</span><br><span class="line">		&#125;</span><br><span class="line">		DataSourceContextHolder.setDS(dataSource);</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	@After(&quot;@annotation(DS)&quot;)</span><br><span class="line">	public void afterSwitchDS(JoinPoint point) &#123;</span><br><span class="line">		DataSourceContextHolder.clearDS();</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>绑定当前线程数据源类：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">public class DataSourceContextHolder &#123;</span><br><span class="line"></span><br><span class="line">	public static final String DEFAULT_DS = DSConfig.DB_MASTER;</span><br><span class="line"></span><br><span class="line">	private static final ThreadLocal&lt;String&gt; DS_HOLDER = new ThreadLocal&lt;&gt;();</span><br><span class="line"></span><br><span class="line">	public static void setDS(String dbType) &#123;</span><br><span class="line">		DS_HOLDER.set(dbType);</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	public static String getDS() &#123;</span><br><span class="line">		return (DS_HOLDER.get());</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	public static void clearDS() &#123;</span><br><span class="line">		DS_HOLDER.remove();</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">



</div>

    <a data-url="http://youanyyou.gitee.io/javastack/2018/04/18/Spring Boot/Spring Boot集成Mybatis双数据源/" data-id="cjg4zd8os004khg8anj0aclfc" class="article-share-link"><i class="fa fa-share"></i>分享到</a>
<script>
    (function ($) {
        // Prevent duplicate binding
        if (typeof(__SHARE_BUTTON_BINDED__) === 'undefined' || !__SHARE_BUTTON_BINDED__) {
            __SHARE_BUTTON_BINDED__ = true;
        } else {
            return;
        }
        $('body').on('click', function() {
            $('.article-share-box.on').removeClass('on');
        }).on('click', '.article-share-link', function(e) {
            e.stopPropagation();

            var $this = $(this),
                url = $this.attr('data-url'),
                encodedUrl = encodeURIComponent(url),
                id = 'article-share-box-' + $this.attr('data-id'),
                offset = $this.offset(),
                box;

            if ($('#' + id).length) {
                box = $('#' + id);

                if (box.hasClass('on')){
                    box.removeClass('on');
                    return;
                }
            } else {
                var html = [
                    '<div id="' + id + '" class="article-share-box">',
                        '<input class="article-share-input" value="' + url + '">',
                        '<div class="article-share-links">',
                            '<a href="https://twitter.com/intent/tweet?url=' + encodedUrl + '" class="fa fa-twitter article-share-twitter" target="_blank" title="Twitter"></a>',
                            '<a href="https://www.facebook.com/sharer.php?u=' + encodedUrl + '" class="fa fa-facebook article-share-facebook" target="_blank" title="Facebook"></a>',
                            '<a href="http://pinterest.com/pin/create/button/?url=' + encodedUrl + '" class="fa fa-pinterest article-share-pinterest" target="_blank" title="Pinterest"></a>',
                            '<a href="https://plus.google.com/share?url=' + encodedUrl + '" class="fa fa-google article-share-google" target="_blank" title="Google+"></a>',
                        '</div>',
                    '</div>'
                ].join('');

              box = $(html);

              $('body').append(box);
            }

            $('.article-share-box.on').hide();

            box.css({
                top: offset.top + 25,
                left: offset.left
            }).addClass('on');

        }).on('click', '.article-share-box', function (e) {
            e.stopPropagation();
        }).on('click', '.article-share-box-input', function () {
            $(this).select();
        }).on('click', '.article-share-box-link', function (e) {
            e.preventDefault();
            e.stopPropagation();

            window.open(this.href, 'article-share-box-window-' + Date.now(), 'width=500,height=450');
        });
    })(jQuery);
</script>

            
    

        </footer>
    </div>
    
</article>



    <article id="post-Spring Boot/Spring Boot发布将jar包转为war包。" class="article article-type-post" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <p><img src="http://p179cyr45.bkt.clouddn.com/18-2-27/88945925.jpg" alt=""></p>
<p>Spring Boot是支持发布jar包和war的，但它推荐的是使用jar形式发布。使用jar包比较方便，但如果是频繁修改更新的项目，需要打补丁包，那这么大的jar包上传都是问题。所以，jar包不一定合适适用所有的场景，如war包更合适，你可以尝试转为传统的war包，这样打补丁包可能更方便。</p>
<h4 id="如何配置打war包呢？"><a href="#如何配置打war包呢？" class="headerlink" title="如何配置打war包呢？"></a>如何配置打war包呢？</h4><p>以下配置以Maven为说明讲解，Gradle的查看类似配置。</p>
<p><strong>1、修改Spring Boot启动类</strong></p>
<p>启动类继承<code>SpringBootServletInitializer</code>类，并覆盖<code>configure</code>方法。</p>
<p>下面是Spring Boot提供的示例代码。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">@SpringBootApplication</span><br><span class="line">public class Application extends SpringBootServletInitializer &#123;</span><br><span class="line"></span><br><span class="line">	@Override</span><br><span class="line">	protected SpringApplicationBuilder configure(SpringApplicationBuilder application) &#123;</span><br><span class="line">		return application.sources(Application.class);</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	public static void main(String[] args) throws Exception &#123;</span><br><span class="line">		SpringApplication.run(Application.class, args);</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>2、修改jar为war包形式</strong></p>
<p>在pom文件中，添加war包配置。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;packaging&gt;war&lt;/packaging&gt;</span><br></pre></td></tr></table></figure>
<p>如果不添加，默认为jar包。</p>
<p><strong>3、去除Spring Boot内置Tomcat</strong></p>
<p>修改自带tomcat依赖范围为provided，防止与外部tomcat发生冲突。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">&lt;dependencies&gt;</span><br><span class="line">	&lt;!-- … --&gt;</span><br><span class="line">	&lt;dependency&gt;</span><br><span class="line">		&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">		&lt;artifactId&gt;spring-boot-starter-tomcat&lt;/artifactId&gt;</span><br><span class="line">		&lt;scope&gt;provided&lt;/scope&gt;</span><br><span class="line">	&lt;/dependency&gt;</span><br><span class="line">	&lt;!-- … --&gt;</span><br><span class="line">&lt;/dependencies&gt;</span><br></pre></td></tr></table></figure>
<p><strong>4、添加war包打包插件</strong></p>
<p>如果你用的是继承spring-boot-starter-parent的形式使用Spring Boot，那可以跳过，因为它已经帮你配置好了。如果你使用的依赖spring-boot-dependencies形式，你需要添加以下插件。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&lt;plugin&gt;</span><br><span class="line">    &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;maven-war-plugin&lt;/artifactId&gt;</span><br><span class="line">    &lt;configuration&gt;</span><br><span class="line">        &lt;failOnMissingWebXml&gt;false&lt;/failOnMissingWebXml&gt;</span><br><span class="line">    &lt;/configuration&gt;</span><br><span class="line">&lt;/plugin&gt;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>failOnMissingWebXml需要开启为false，不然打包会报没有web.xml错误。</p>
</blockquote>
<h4 id="如何打war包？"><a href="#如何打war包？" class="headerlink" title="如何打war包？"></a>如何打war包？</h4><p>打war包方式和打jar包方式一样，没有区别。</p>
<ul>
<li><p>在Maven中使用<code>mvn clean package</code>命令即可打包。</p>
</li>
<li><p>在Idea中可以这样设置打包：</p>
</li>
</ul>
<p><img src="http://p179cyr45.bkt.clouddn.com/18-2-8/28070341.jpg" alt=""></p>
<p>改在war包后，发现打war包比打jar要上好多。</p>
<h4 id="jar包转war包有什么影响？"><a href="#jar包转war包有什么影响？" class="headerlink" title="jar包转war包有什么影响？"></a>jar包转war包有什么影响？</h4><p>1、application配置文件中的server.xx等关于容器的配置就无效了，改配置需要在外部tomcat中进行。</p>
<p>2、Spring Boot的升级是否需要Tomcat跟着升级？需要观察。</p>
<p>3、打war包比打jar明显要变慢好多。。</p>
<p>暂时还没遇到其他问题，大家对此有什么看法都可以在下方留言。</p>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">



</div>

    <a data-url="http://youanyyou.gitee.io/javastack/2018/04/18/Spring Boot/Spring Boot发布将jar包转为war包。/" data-id="cjg4zd8o1003rhg8aiyc69cmx" class="article-share-link"><i class="fa fa-share"></i>分享到</a>
<script>
    (function ($) {
        // Prevent duplicate binding
        if (typeof(__SHARE_BUTTON_BINDED__) === 'undefined' || !__SHARE_BUTTON_BINDED__) {
            __SHARE_BUTTON_BINDED__ = true;
        } else {
            return;
        }
        $('body').on('click', function() {
            $('.article-share-box.on').removeClass('on');
        }).on('click', '.article-share-link', function(e) {
            e.stopPropagation();

            var $this = $(this),
                url = $this.attr('data-url'),
                encodedUrl = encodeURIComponent(url),
                id = 'article-share-box-' + $this.attr('data-id'),
                offset = $this.offset(),
                box;

            if ($('#' + id).length) {
                box = $('#' + id);

                if (box.hasClass('on')){
                    box.removeClass('on');
                    return;
                }
            } else {
                var html = [
                    '<div id="' + id + '" class="article-share-box">',
                        '<input class="article-share-input" value="' + url + '">',
                        '<div class="article-share-links">',
                            '<a href="https://twitter.com/intent/tweet?url=' + encodedUrl + '" class="fa fa-twitter article-share-twitter" target="_blank" title="Twitter"></a>',
                            '<a href="https://www.facebook.com/sharer.php?u=' + encodedUrl + '" class="fa fa-facebook article-share-facebook" target="_blank" title="Facebook"></a>',
                            '<a href="http://pinterest.com/pin/create/button/?url=' + encodedUrl + '" class="fa fa-pinterest article-share-pinterest" target="_blank" title="Pinterest"></a>',
                            '<a href="https://plus.google.com/share?url=' + encodedUrl + '" class="fa fa-google article-share-google" target="_blank" title="Google+"></a>',
                        '</div>',
                    '</div>'
                ].join('');

              box = $(html);

              $('body').append(box);
            }

            $('.article-share-box.on').hide();

            box.css({
                top: offset.top + 25,
                left: offset.left
            }).addClass('on');

        }).on('click', '.article-share-box', function (e) {
            e.stopPropagation();
        }).on('click', '.article-share-box-input', function () {
            $(this).select();
        }).on('click', '.article-share-box-link', function (e) {
            e.preventDefault();
            e.stopPropagation();

            window.open(this.href, 'article-share-box-window-' + Date.now(), 'width=500,height=450');
        });
    })(jQuery);
</script>

            
    

        </footer>
    </div>
    
</article>



    <article id="post-Spring Boot/Spring Boot整合Thymeleaf模板引擎" class="article article-type-post" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <h2 id="什么是Thymeleaf"><a href="#什么是Thymeleaf" class="headerlink" title="什么是Thymeleaf"></a>什么是Thymeleaf</h2><p>Thymeleaf是一款用于渲染XML、XHTML、HTML5内容的模板引擎。类似Velocity，FreeMaker模板引擎，它也可以轻易的与Spring MVC等Web框架进行集成作为Web应用的模板引擎。</p>
<p>Thymeleaf也是Spring Boot首要支持的模板引擎，并且在最新的Spring Boot版本中已经不再支持Velocity了。</p>
<blockquote>
<p>官网：<a href="http://www.thymeleaf.org/" target="_blank" rel="noopener">http://www.thymeleaf.org/</a></p>
</blockquote>
<h2 id="引入依赖"><a href="#引入依赖" class="headerlink" title="引入依赖"></a>引入依赖</h2><p>需要引入Spring Boot的Thymeleaf启动器依赖。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&lt;dependency&gt;</span><br><span class="line">    &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;spring-boot-starter-thymeleaf&lt;/artifactId&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br></pre></td></tr></table></figure>
<p>引入该依赖后会自动引入web依赖，不需要再单独引入web依赖。</p>
<h2 id="自动配置说明"><a href="#自动配置说明" class="headerlink" title="自动配置说明"></a>自动配置说明</h2><p>下面是Thymeleaf的自动配置相关类。</p>
<p>Thymeleaf的自动配置类：</p>
<blockquote>
<p>org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration</p>
</blockquote>
<p>Thymeleaf的自动配置参数类：</p>
<blockquote>
<p>org.springframework.boot.autoconfigure.thymeleaf.ThymeleafProperties</p>
</blockquote>
<p>查看参数源码：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">private static final Charset DEFAULT_ENCODING = Charset.forName(&quot;UTF-8&quot;);</span><br><span class="line"></span><br><span class="line">private static final MimeType DEFAULT_CONTENT_TYPE = MimeType.valueOf(&quot;text/html&quot;);</span><br><span class="line"></span><br><span class="line">public static final String DEFAULT_PREFIX = &quot;classpath:/templates/&quot;;</span><br><span class="line"></span><br><span class="line">public static final String DEFAULT_SUFFIX = &quot;.html&quot;;</span><br></pre></td></tr></table></figure>
<p>默认的编码是：UTF-8</p>
<p>默认的类型是：text/html</p>
<p>默认的模板文件目录是：classpath:/templates/</p>
<p>默认的模板文件后缀是：.html</p>
<p>这些参数都可以通过在application配置文件中指定<code>spring.thymeleaf.xx</code>进行更改，更多可参考该参数类。</p>
<h2 id="实战"><a href="#实战" class="headerlink" title="实战"></a>实战</h2><p>知道了自动配置的原理，所以我们可以知道怎么做了。</p>
<p>一、在resources目录下创建templates目录。</p>
<p>二、在templates目录下创建.html模板文件。</p>
<p>三、使用模板：</p>
<p>1、模板文件头部使用<code>&lt;html xmlns:th=&quot;http://www.thymeleaf.org&quot;&gt;</code>定义。</p>
<p>2、html标签上使用<code>th:</code>开头标识作为前缀。</p>
<p>3、通过<code>@{}</code>引入web静态文件。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;link rel=&quot;stylesheet&quot; th:href=&quot;@&#123;/css/jquery.min.css&#125;&quot;/&gt;</span><br></pre></td></tr></table></figure>
<p>4、访问数据</p>
<p>访问springmvc中的model数据：<code>${user.name}</code>，访问更多不同对象的数据请<a href="http://www.thymeleaf.org/doc/articles/springmvcaccessdata.html" target="_blank" rel="noopener">点击</a>参考官方定义。</p>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">



</div>

    <a data-url="http://youanyyou.gitee.io/javastack/2018/04/18/Spring Boot/Spring Boot整合Thymeleaf模板引擎/" data-id="cjg4zd8o80042hg8avvz8y0lm" class="article-share-link"><i class="fa fa-share"></i>分享到</a>
<script>
    (function ($) {
        // Prevent duplicate binding
        if (typeof(__SHARE_BUTTON_BINDED__) === 'undefined' || !__SHARE_BUTTON_BINDED__) {
            __SHARE_BUTTON_BINDED__ = true;
        } else {
            return;
        }
        $('body').on('click', function() {
            $('.article-share-box.on').removeClass('on');
        }).on('click', '.article-share-link', function(e) {
            e.stopPropagation();

            var $this = $(this),
                url = $this.attr('data-url'),
                encodedUrl = encodeURIComponent(url),
                id = 'article-share-box-' + $this.attr('data-id'),
                offset = $this.offset(),
                box;

            if ($('#' + id).length) {
                box = $('#' + id);

                if (box.hasClass('on')){
                    box.removeClass('on');
                    return;
                }
            } else {
                var html = [
                    '<div id="' + id + '" class="article-share-box">',
                        '<input class="article-share-input" value="' + url + '">',
                        '<div class="article-share-links">',
                            '<a href="https://twitter.com/intent/tweet?url=' + encodedUrl + '" class="fa fa-twitter article-share-twitter" target="_blank" title="Twitter"></a>',
                            '<a href="https://www.facebook.com/sharer.php?u=' + encodedUrl + '" class="fa fa-facebook article-share-facebook" target="_blank" title="Facebook"></a>',
                            '<a href="http://pinterest.com/pin/create/button/?url=' + encodedUrl + '" class="fa fa-pinterest article-share-pinterest" target="_blank" title="Pinterest"></a>',
                            '<a href="https://plus.google.com/share?url=' + encodedUrl + '" class="fa fa-google article-share-google" target="_blank" title="Google+"></a>',
                        '</div>',
                    '</div>'
                ].join('');

              box = $(html);

              $('body').append(box);
            }

            $('.article-share-box.on').hide();

            box.css({
                top: offset.top + 25,
                left: offset.left
            }).addClass('on');

        }).on('click', '.article-share-box', function (e) {
            e.stopPropagation();
        }).on('click', '.article-share-box-input', function () {
            $(this).select();
        }).on('click', '.article-share-box-link', function (e) {
            e.preventDefault();
            e.stopPropagation();

            window.open(this.href, 'article-share-box-window-' + Date.now(), 'width=500,height=450');
        });
    })(jQuery);
</script>

            
    

        </footer>
    </div>
    
</article>



    <article id="post-Spring Boot/Spring Boot功能实战" class="article article-type-post" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <h2 id="添加web功能启动器"><a href="#添加web功能启动器" class="headerlink" title="添加web功能启动器"></a>添加web功能启动器</h2><p>添加了Spring Boot基础依赖后，如要使用web mvc功能，只需要添加如下启动器即可，Spring Boot会自动装配web功能。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&lt;dependencies&gt;</span><br><span class="line">    &lt;dependency&gt;</span><br><span class="line">        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">        &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;</span><br><span class="line">    &lt;/dependency&gt;</span><br><span class="line">&lt;/dependencies&gt;</span><br></pre></td></tr></table></figure>
<h2 id="添加启动类"><a href="#添加启动类" class="headerlink" title="添加启动类"></a>添加启动类</h2><p>然后添加启动类，建议放在根包下，这里把Controller和启动类放在一起也是没问题的，实际请分包出来。</p>
<p>启动类必须要有main方法，并添加启动方法。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">package hello;</span><br><span class="line"></span><br><span class="line">import org.springframework.boot.*;</span><br><span class="line">import org.springframework.boot.autoconfigure.*;</span><br><span class="line">import org.springframework.stereotype.*;</span><br><span class="line">import org.springframework.web.bind.annotation.*;</span><br><span class="line"></span><br><span class="line">@Controller</span><br><span class="line">@SpringBootApplication</span><br><span class="line">public class SampleController &#123;</span><br><span class="line"></span><br><span class="line">    @RequestMapping(&quot;/&quot;)</span><br><span class="line">    @ResponseBody</span><br><span class="line">    String home() &#123;</span><br><span class="line">        return &quot;Hello World!&quot;;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    public static void main(String[] args) throws Exception &#123;</span><br><span class="line">        SpringApplication.run(SampleController.class, args);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="添加编译打包插件"><a href="#添加编译打包插件" class="headerlink" title="添加编译打包插件"></a>添加编译打包插件</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">&lt;build&gt;</span><br><span class="line">	&lt;plugins&gt;</span><br><span class="line">		&lt;plugin&gt;</span><br><span class="line">			&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">			&lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;</span><br><span class="line">			&lt;executions&gt;</span><br><span class="line">				&lt;execution&gt;</span><br><span class="line">					&lt;goals&gt;</span><br><span class="line">						&lt;goal&gt;repackage&lt;/goal&gt;</span><br><span class="line">					&lt;/goals&gt;</span><br><span class="line">					&lt;configuration&gt;</span><br><span class="line">						&lt;classifier&gt;exec&lt;/classifier&gt;</span><br><span class="line">						&lt;fork&gt;true&lt;/fork&gt;</span><br><span class="line">						&lt;excludeDevtools&gt;true&lt;/excludeDevtools&gt;</span><br><span class="line">					&lt;/configuration&gt;</span><br><span class="line">				&lt;/execution&gt;</span><br><span class="line">			&lt;/executions&gt;</span><br><span class="line">		&lt;/plugin&gt;</span><br><span class="line">	&lt;/plugins&gt;</span><br><span class="line">&lt;/build&gt;</span><br></pre></td></tr></table></figure>
<h2 id="运行Spring-Boot的3种方式"><a href="#运行Spring-Boot的3种方式" class="headerlink" title="运行Spring Boot的3种方式"></a>运行Spring Boot的3种方式</h2><ol>
<li>运行启动类的main方法。</li>
<li>使用spring-boot:run命令。</li>
<li>打成jar包后使用java -jar xx.jar命令。</li>
</ol>
<p>Spring Boot默认的端口是8080，可以通过server.port=8081来修改，或者通过命令行指定也行。</p>
<p>启动工程后，访问localhost:8080/就能输出：Hello World!</p>
<h2 id="Spring-Boot快速构建方式"><a href="#Spring-Boot快速构建方式" class="headerlink" title="Spring Boot快速构建方式"></a>Spring Boot快速构建方式</h2><p>上面是通过maven手动创建工程的方式添加Spring Boot应用 ，当然新手也可以打开Spring Boot的快速构建网站<a href="http://start.spring.io/，来选择对应的启动器生成项目，最后导入进来即可。" target="_blank" rel="noopener">http://start.spring.io/，来选择对应的启动器生成项目，最后导入进来即可。</a></p>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">



</div>

    <a data-url="http://youanyyou.gitee.io/javastack/2018/04/18/Spring Boot/Spring Boot功能实战/" data-id="cjg4zd8nr003phg8ai6kmt1gp" class="article-share-link"><i class="fa fa-share"></i>分享到</a>
<script>
    (function ($) {
        // Prevent duplicate binding
        if (typeof(__SHARE_BUTTON_BINDED__) === 'undefined' || !__SHARE_BUTTON_BINDED__) {
            __SHARE_BUTTON_BINDED__ = true;
        } else {
            return;
        }
        $('body').on('click', function() {
            $('.article-share-box.on').removeClass('on');
        }).on('click', '.article-share-link', function(e) {
            e.stopPropagation();

            var $this = $(this),
                url = $this.attr('data-url'),
                encodedUrl = encodeURIComponent(url),
                id = 'article-share-box-' + $this.attr('data-id'),
                offset = $this.offset(),
                box;

            if ($('#' + id).length) {
                box = $('#' + id);

                if (box.hasClass('on')){
                    box.removeClass('on');
                    return;
                }
            } else {
                var html = [
                    '<div id="' + id + '" class="article-share-box">',
                        '<input class="article-share-input" value="' + url + '">',
                        '<div class="article-share-links">',
                            '<a href="https://twitter.com/intent/tweet?url=' + encodedUrl + '" class="fa fa-twitter article-share-twitter" target="_blank" title="Twitter"></a>',
                            '<a href="https://www.facebook.com/sharer.php?u=' + encodedUrl + '" class="fa fa-facebook article-share-facebook" target="_blank" title="Facebook"></a>',
                            '<a href="http://pinterest.com/pin/create/button/?url=' + encodedUrl + '" class="fa fa-pinterest article-share-pinterest" target="_blank" title="Pinterest"></a>',
                            '<a href="https://plus.google.com/share?url=' + encodedUrl + '" class="fa fa-google article-share-google" target="_blank" title="Google+"></a>',
                        '</div>',
                    '</div>'
                ].join('');

              box = $(html);

              $('body').append(box);
            }

            $('.article-share-box.on').hide();

            box.css({
                top: offset.top + 25,
                left: offset.left
            }).addClass('on');

        }).on('click', '.article-share-box', function (e) {
            e.stopPropagation();
        }).on('click', '.article-share-box-input', function () {
            $(this).select();
        }).on('click', '.article-share-box-link', function (e) {
            e.preventDefault();
            e.stopPropagation();

            window.open(this.href, 'article-share-box-window-' + Date.now(), 'width=500,height=450');
        });
    })(jQuery);
</script>

            
    

        </footer>
    </div>
    
</article>



    <article id="post-Spring Boot/Spring Boot Runner启动器" class="article article-type-post" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <h2 id="Runner启动器"><a href="#Runner启动器" class="headerlink" title="Runner启动器"></a>Runner启动器</h2><p>如果你想在Spring Boot启动的时候运行一些特定的代码，你可以实现接口<code>ApplicationRunner</code>或者<code>CommandLineRunner</code>，这两个接口实现方式一样，它们都只提供了一个run方法。</p>
<p><strong>CommandLineRunner</strong>：启动获取命令行参数。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">public interface CommandLineRunner &#123;</span><br><span class="line"></span><br><span class="line">	/**</span><br><span class="line">	 * Callback used to run the bean.</span><br><span class="line">	 * @param args incoming main method arguments</span><br><span class="line">	 * @throws Exception on error</span><br><span class="line">	 */</span><br><span class="line">	void run(String... args) throws Exception;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>ApplicationRunner</strong>：启动获取应用启动的时候参数。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">public interface ApplicationRunner &#123;</span><br><span class="line"></span><br><span class="line">	/**</span><br><span class="line">	 * Callback used to run the bean.</span><br><span class="line">	 * @param args incoming application arguments</span><br><span class="line">	 * @throws Exception on error</span><br><span class="line">	 */</span><br><span class="line">	void run(ApplicationArguments args) throws Exception;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="使用方式"><a href="#使用方式" class="headerlink" title="使用方式"></a>使用方式</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">import org.springframework.boot.*</span><br><span class="line">import org.springframework.stereotype.*</span><br><span class="line"></span><br><span class="line">@Component</span><br><span class="line">public class MyBean implements CommandLineRunner &#123;</span><br><span class="line"></span><br><span class="line">    public void run(String... args) &#123;</span><br><span class="line">        // Do something...</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>或者这样</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">@Bean</span><br><span class="line">public CommandLineRunner init() &#123;</span><br><span class="line"></span><br><span class="line">	return (String... strings) -&gt; &#123;</span><br><span class="line">	</span><br><span class="line">	&#125;;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="启动顺序"><a href="#启动顺序" class="headerlink" title="启动顺序"></a>启动顺序</h2><p>如果启动的时候有多个ApplicationRunner和CommandLineRunner，想控制它们的启动顺序，可以实现<code>org.springframework.core.Ordered</code>接口或者使用<code>org.springframework.core.annotation.Order</code>注解。</p>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">



</div>

    <a data-url="http://youanyyou.gitee.io/javastack/2018/04/18/Spring Boot/Spring Boot Runner启动器/" data-id="cjg4zd8n6002vhg8atv8fxk44" class="article-share-link"><i class="fa fa-share"></i>分享到</a>
<script>
    (function ($) {
        // Prevent duplicate binding
        if (typeof(__SHARE_BUTTON_BINDED__) === 'undefined' || !__SHARE_BUTTON_BINDED__) {
            __SHARE_BUTTON_BINDED__ = true;
        } else {
            return;
        }
        $('body').on('click', function() {
            $('.article-share-box.on').removeClass('on');
        }).on('click', '.article-share-link', function(e) {
            e.stopPropagation();

            var $this = $(this),
                url = $this.attr('data-url'),
                encodedUrl = encodeURIComponent(url),
                id = 'article-share-box-' + $this.attr('data-id'),
                offset = $this.offset(),
                box;

            if ($('#' + id).length) {
                box = $('#' + id);

                if (box.hasClass('on')){
                    box.removeClass('on');
                    return;
                }
            } else {
                var html = [
                    '<div id="' + id + '" class="article-share-box">',
                        '<input class="article-share-input" value="' + url + '">',
                        '<div class="article-share-links">',
                            '<a href="https://twitter.com/intent/tweet?url=' + encodedUrl + '" class="fa fa-twitter article-share-twitter" target="_blank" title="Twitter"></a>',
                            '<a href="https://www.facebook.com/sharer.php?u=' + encodedUrl + '" class="fa fa-facebook article-share-facebook" target="_blank" title="Facebook"></a>',
                            '<a href="http://pinterest.com/pin/create/button/?url=' + encodedUrl + '" class="fa fa-pinterest article-share-pinterest" target="_blank" title="Pinterest"></a>',
                            '<a href="https://plus.google.com/share?url=' + encodedUrl + '" class="fa fa-google article-share-google" target="_blank" title="Google+"></a>',
                        '</div>',
                    '</div>'
                ].join('');

              box = $(html);

              $('body').append(box);
            }

            $('.article-share-box.on').hide();

            box.css({
                top: offset.top + 25,
                left: offset.left
            }).addClass('on');

        }).on('click', '.article-share-box', function (e) {
            e.stopPropagation();
        }).on('click', '.article-share-box-input', function () {
            $(this).select();
        }).on('click', '.article-share-box-link', function (e) {
            e.preventDefault();
            e.stopPropagation();

            window.open(this.href, 'article-share-box-window-' + Date.now(), 'width=500,height=450');
        });
    })(jQuery);
</script>

            
    

        </footer>
    </div>
    
</article>



    <article id="post-Spring Boot/Spring Boot Server容器配置" class="article article-type-post" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <h2 id="参数配置容器"><a href="#参数配置容器" class="headerlink" title="参数配置容器"></a>参数配置容器</h2><p>server.xx开头的是所有servlet容器通用的配置，server.tomcat.xx开头的是tomcat特有的参数，其它类似。</p>
<p>所有参数绑定配置类：org.springframework.boot.autoconfigure.web.ServerProperties</p>
<h2 id="代码配置容器"><a href="#代码配置容器" class="headerlink" title="代码配置容器"></a>代码配置容器</h2><p>除了利用上面的参数来自动配置servlet容器，还可以通过代码的方式。可以直接实现EmbeddedServletContainerCustomizer这个接口，ServerProperties也是实现这个接口的。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">@ConfigurationProperties(prefix = &quot;server&quot;, ignoreUnknownFields = true)</span><br><span class="line">public class ServerProperties</span><br><span class="line">		implements EmbeddedServletContainerCustomizer, EnvironmentAware, Ordered &#123;</span><br><span class="line">...</span><br></pre></td></tr></table></figure>
<p>当然如果是Tomcat、Jetty、Undertow也可以使用下面对应的特定的容器工厂类。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">// Jetty</span><br><span class="line">org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory</span><br><span class="line"></span><br><span class="line">// Tomcat</span><br><span class="line">org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory</span><br><span class="line"></span><br><span class="line">// Undertow</span><br><span class="line">org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory</span><br></pre></td></tr></table></figure>
<h2 id="替换Tomcat"><a href="#替换Tomcat" class="headerlink" title="替换Tomcat"></a>替换Tomcat</h2><blockquote>
<p>spring-boot-starter-web brings Tomcat with spring-boot-starter-tomcat, but spring-boot-starter-jetty and spring-boot-starter-undertow can be used instead.</p>
</blockquote>
<p>spring-boot-starter-web自动携带了tomcat依赖，但也可以替换成jetty和undertow，下面是一个替换jetty的示例。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">&lt;dependency&gt;</span><br><span class="line">    &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;</span><br><span class="line">    &lt;exclusions&gt;</span><br><span class="line">        &lt;!-- Exclude the Tomcat dependency --&gt;</span><br><span class="line">        &lt;exclusion&gt;</span><br><span class="line">            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;spring-boot-starter-tomcat&lt;/artifactId&gt;</span><br><span class="line">        &lt;/exclusion&gt;</span><br><span class="line">    &lt;/exclusions&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br><span class="line">&lt;!-- Use Jetty instead --&gt;</span><br><span class="line">&lt;dependency&gt;</span><br><span class="line">    &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;spring-boot-starter-jetty&lt;/artifactId&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br></pre></td></tr></table></figure>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">



</div>

    <a data-url="http://youanyyou.gitee.io/javastack/2018/04/18/Spring Boot/Spring Boot Server容器配置/" data-id="cjg4zd8nb0032hg8ae7rqaxkc" class="article-share-link"><i class="fa fa-share"></i>分享到</a>
<script>
    (function ($) {
        // Prevent duplicate binding
        if (typeof(__SHARE_BUTTON_BINDED__) === 'undefined' || !__SHARE_BUTTON_BINDED__) {
            __SHARE_BUTTON_BINDED__ = true;
        } else {
            return;
        }
        $('body').on('click', function() {
            $('.article-share-box.on').removeClass('on');
        }).on('click', '.article-share-link', function(e) {
            e.stopPropagation();

            var $this = $(this),
                url = $this.attr('data-url'),
                encodedUrl = encodeURIComponent(url),
                id = 'article-share-box-' + $this.attr('data-id'),
                offset = $this.offset(),
                box;

            if ($('#' + id).length) {
                box = $('#' + id);

                if (box.hasClass('on')){
                    box.removeClass('on');
                    return;
                }
            } else {
                var html = [
                    '<div id="' + id + '" class="article-share-box">',
                        '<input class="article-share-input" value="' + url + '">',
                        '<div class="article-share-links">',
                            '<a href="https://twitter.com/intent/tweet?url=' + encodedUrl + '" class="fa fa-twitter article-share-twitter" target="_blank" title="Twitter"></a>',
                            '<a href="https://www.facebook.com/sharer.php?u=' + encodedUrl + '" class="fa fa-facebook article-share-facebook" target="_blank" title="Facebook"></a>',
                            '<a href="http://pinterest.com/pin/create/button/?url=' + encodedUrl + '" class="fa fa-pinterest article-share-pinterest" target="_blank" title="Pinterest"></a>',
                            '<a href="https://plus.google.com/share?url=' + encodedUrl + '" class="fa fa-google article-share-google" target="_blank" title="Google+"></a>',
                        '</div>',
                    '</div>'
                ].join('');

              box = $(html);

              $('body').append(box);
            }

            $('.article-share-box.on').hide();

            box.css({
                top: offset.top + 25,
                left: offset.left
            }).addClass('on');

        }).on('click', '.article-share-box', function (e) {
            e.stopPropagation();
        }).on('click', '.article-share-box-input', function () {
            $(this).select();
        }).on('click', '.article-share-box-link', function (e) {
            e.preventDefault();
            e.stopPropagation();

            window.open(this.href, 'article-share-box-window-' + Date.now(), 'width=500,height=450');
        });
    })(jQuery);
</script>

            
    

        </footer>
    </div>
    
</article>



    <nav id="page-nav">
        <a class="extend prev" rel="prev" href="/javastack/">&laquo; 上一页</a><a class="page-number" href="/javastack/">1</a><span class="page-number current">2</span><a class="page-number" href="/javastack/page/3/">3</a><a class="page-number" href="/javastack/page/4/">4</a><span class="space">&hellip;</span><a class="page-number" href="/javastack/page/12/">12</a><a class="extend next" rel="next" href="/javastack/page/3/">下一页 &raquo;</a>
    </nav>
</section>
            
                
<aside id="sidebar">
   
        
    <div class="widget-wrap">
        <h3 class="widget-title">分类</h3>
        <div class="widget">
            <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/javastack/categories/Java/">Java</a><span class="category-list-count">37</span><ul class="category-list-child"><li class="category-list-item"><a class="category-list-link" href="/javastack/categories/Java/多线程/">多线程</a><span class="category-list-count">3</span></li><li class="category-list-item"><a class="category-list-link" href="/javastack/categories/Java/新特性/">新特性</a><span class="category-list-count">10</span></li></ul></li><li class="category-list-item"><a class="category-list-link" href="/javastack/categories/Maven/">Maven</a><span class="category-list-count">4</span></li><li class="category-list-item"><a class="category-list-link" href="/javastack/categories/Mybatis/">Mybatis</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/javastack/categories/Netty/">Netty</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/javastack/categories/Tomcat/">Tomcat</a><span class="category-list-count">3</span></li><li class="category-list-item"><a class="category-list-link" href="/javastack/categories/书籍推荐/">书籍推荐</a><span class="category-list-count">6</span></li><li class="category-list-item"><a class="category-list-link" href="/javastack/categories/云计算/">云计算</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/javastack/categories/开源项目/">开源项目</a><span class="category-list-count">10</span></li><li class="category-list-item"><a class="category-list-link" href="/javastack/categories/测试/">测试</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/javastack/categories/漏洞/">漏洞</a><span class="category-list-count">2</span></li><li class="category-list-item"><a class="category-list-link" href="/javastack/categories/程序人生/">程序人生</a><span class="category-list-count">3</span></li><li class="category-list-item"><a class="category-list-link" href="/javastack/categories/算法/">算法</a><span class="category-list-count">2</span></li><li class="category-list-item"><a class="category-list-link" href="/javastack/categories/编程语言/">编程语言</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/javastack/categories/行业动态/">行业动态</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/javastack/categories/连接池/">连接池</a><span class="category-list-count">2</span></li></ul>
        </div>
    </div>

    
        
    <div class="widget-wrap">
        <h3 class="widget-title">技术栈</h3>
        <div class="widget tagcloud">
            <a href="/javastack/tags/CAT/" style="font-size: 10px;">CAT</a> <a href="/javastack/tags/Cobar/" style="font-size: 10px;">Cobar</a> <a href="/javastack/tags/Cookie/" style="font-size: 10px;">Cookie</a> <a href="/javastack/tags/Disconf/" style="font-size: 10px;">Disconf</a> <a href="/javastack/tags/Druid/" style="font-size: 12.86px;">Druid</a> <a href="/javastack/tags/Eclipse/" style="font-size: 10px;">Eclipse</a> <a href="/javastack/tags/Facebook/" style="font-size: 10px;">Facebook</a> <a href="/javastack/tags/IP/" style="font-size: 10px;">IP</a> <a href="/javastack/tags/IaaS/" style="font-size: 10px;">IaaS</a> <a href="/javastack/tags/JVM/" style="font-size: 10px;">JVM</a> <a href="/javastack/tags/Java/" style="font-size: 20px;">Java</a> <a href="/javastack/tags/Jodd/" style="font-size: 10px;">Jodd</a> <a href="/javastack/tags/Junit/" style="font-size: 10px;">Junit</a> <a href="/javastack/tags/Kotlin/" style="font-size: 10px;">Kotlin</a> <a href="/javastack/tags/LVS/" style="font-size: 10px;">LVS</a> <a href="/javastack/tags/Maven/" style="font-size: 14.29px;">Maven</a> <a href="/javastack/tags/Mybatis/" style="font-size: 10px;">Mybatis</a> <a href="/javastack/tags/NIO/" style="font-size: 10px;">NIO</a> <a href="/javastack/tags/Netty/" style="font-size: 10px;">Netty</a> <a href="/javastack/tags/Nginx/" style="font-size: 10px;">Nginx</a> <a href="/javastack/tags/Oracle/" style="font-size: 11.43px;">Oracle</a> <a href="/javastack/tags/PaaS/" style="font-size: 10px;">PaaS</a> <a href="/javastack/tags/Python/" style="font-size: 10px;">Python</a> <a href="/javastack/tags/SaaS/" style="font-size: 10px;">SaaS</a> <a href="/javastack/tags/Squid/" style="font-size: 10px;">Squid</a> <a href="/javastack/tags/Tengine/" style="font-size: 10px;">Tengine</a> <a href="/javastack/tags/Thrift/" style="font-size: 10px;">Thrift</a> <a href="/javastack/tags/Tomcat/" style="font-size: 12.86px;">Tomcat</a> <a href="/javastack/tags/https/" style="font-size: 10px;">https</a> <a href="/javastack/tags/jdk10/" style="font-size: 10px;">jdk10</a> <a href="/javastack/tags/jdk7/" style="font-size: 10px;">jdk7</a> <a href="/javastack/tags/jdk8/" style="font-size: 17.14px;">jdk8</a> <a href="/javastack/tags/jdk9/" style="font-size: 10px;">jdk9</a> <a href="/javastack/tags/书籍/" style="font-size: 15.71px;">书籍</a> <a href="/javastack/tags/云计算/" style="font-size: 10px;">云计算</a> <a href="/javastack/tags/代理/" style="font-size: 10px;">代理</a> <a href="/javastack/tags/分布式/" style="font-size: 11.43px;">分布式</a> <a href="/javastack/tags/区块链/" style="font-size: 10px;">区块链</a> <a href="/javastack/tags/多线程/" style="font-size: 12.86px;">多线程</a> <a href="/javastack/tags/安全/" style="font-size: 10px;">安全</a> <a href="/javastack/tags/开源项目/" style="font-size: 18.57px;">开源项目</a> <a href="/javastack/tags/性能优化/" style="font-size: 10px;">性能优化</a> <a href="/javastack/tags/攻击/" style="font-size: 10px;">攻击</a> <a href="/javastack/tags/数据库/" style="font-size: 10px;">数据库</a> <a href="/javastack/tags/架构师/" style="font-size: 11.43px;">架构师</a> <a href="/javastack/tags/测试/" style="font-size: 10px;">测试</a> <a href="/javastack/tags/漏洞/" style="font-size: 11.43px;">漏洞</a> <a href="/javastack/tags/监控/" style="font-size: 11.43px;">监控</a> <a href="/javastack/tags/程序人生/" style="font-size: 12.86px;">程序人生</a> <a href="/javastack/tags/算法/" style="font-size: 11.43px;">算法</a> <a href="/javastack/tags/缓存/" style="font-size: 10px;">缓存</a> <a href="/javastack/tags/编程语言/" style="font-size: 10px;">编程语言</a> <a href="/javastack/tags/腾讯/" style="font-size: 10px;">腾讯</a> <a href="/javastack/tags/行业动态/" style="font-size: 10px;">行业动态</a> <a href="/javastack/tags/负载均衡/" style="font-size: 11.43px;">负载均衡</a> <a href="/javastack/tags/连接池/" style="font-size: 12.86px;">连接池</a> <a href="/javastack/tags/阿里巴巴/" style="font-size: 14.29px;">阿里巴巴</a> <a href="/javastack/tags/高并发/" style="font-size: 10px;">高并发</a>
        </div>
    </div>

    
        
    <div class="widget-wrap widget-list">
        <h3 class="widget-title">链接</h3>
        <div class="widget">
            <ul>
                
                    <li>
                        <a href="http://hexo.io">Hexo</a>
                    </li>
                
            </ul>
        </div>
    </div>


    
    <div id="toTop" class="fa fa-angle-up"></div>
</aside>

            
        </div>
        <footer id="footer">
    <div class="outer">
        <div id="footer-info" class="inner">
            &copy; 2018 Java技术栈 版权所有
            <br>
            Powered by <a href="http://www.javastack.cn/" target="_self">javastack.cn</a>. 
        </div>
    </div>
</footer>
        


    
        <script src="/javastack/libs/lightgallery/js/lightgallery.min.js"></script>
        <script src="/javastack/libs/lightgallery/js/lg-thumbnail.min.js"></script>
        <script src="/javastack/libs/lightgallery/js/lg-pager.min.js"></script>
        <script src="/javastack/libs/lightgallery/js/lg-autoplay.min.js"></script>
        <script src="/javastack/libs/lightgallery/js/lg-fullscreen.min.js"></script>
        <script src="/javastack/libs/lightgallery/js/lg-zoom.min.js"></script>
        <script src="/javastack/libs/lightgallery/js/lg-hash.min.js"></script>
        <script src="/javastack/libs/lightgallery/js/lg-share.min.js"></script>
        <script src="/javastack/libs/lightgallery/js/lg-video.min.js"></script>
    
    
        <script src="/javastack/libs/justified-gallery/jquery.justifiedGallery.min.js"></script>
    
    



<!-- Custom Scripts -->
<script src="/javastack/js/main.js"></script>

    </div>
</body>
</html>